@import url("caliba.css");
@import url("fonts.css");
@import url("door.css");

/* The producer room, on the locked Caliba design system, built to the drawing
 * approved on 10 September 2026 (docs/design/producer-room/producer-room.html,
 * pinned by sha in docs/design/REGISTER.json).
 *
 * Vocabulary and grammar both come from UI/DESIGN_SYSTEM.md: the literal
 * colours, the closed type scale, the five legal radii, the motion and the
 * copy rules, and above them the clarity rules that decide whether a surface
 * is allowed to exist in the shape it is in. Legal tokens are the floor, not
 * the pass, so the shape of these pages answers the checklist rather than
 * merely spelling itself in approved values.
 *
 * Where the system is silent, FABLE's philosophy holds: the work sits on the
 * stage well and is never inset in a frame, surfaces do the separating instead
 * of borders, and exactly one decision per screen wears the cream.
 *
 * THE STATE COLOURS ARE THE SYSTEM'S, NOT THE DRAWING'S. The four state
 * literals the drawing declares are the pre-lift ones, and the lift of
 * 10 September retired all four the same day; building to them would put the
 * second gold back and undo the chroma David ruled. Every colour on this sheet
 * is read out of caliba.css and none is spelled here. See tests/tokens.mjs,
 * which fails on any literal this sheet spells out.
 *
 * The client's room keeps app.css until its own reskin is approved, which is
 * why this is a second stylesheet and not a section of the first.
 *
 * Type: the system names Switzer, loaded from Fontshare. Nothing in this
 * deployment asks a third party for anything, so Switzer is served from
 * public/assets/fonts at 400/500/600/700 through fonts.css, and the system's own
 * fallback stack stands behind it.
 */

/* Every token is the design system's, in public/assets/caliba.css, imported
 * above and shared with the client room's app.css. Nothing is defined twice:
 * two copies of one palette is how the two products came apart the first
 * time. What is left here is the producer room, not the system. */

* { box-sizing: border-box; margin: 0; padding: 0; }

html { min-width: 320px; overflow-x: clip; color-scheme: dark; -webkit-text-size-adjust: 100%; }

body {
  background: var(--void);
  color: var(--ink2);
  font: var(--role-secondary);
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  -webkit-user-select: none; user-select: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100dvh;
}
/* Film grain, the room's one texture, at three and a half per cent: the
 * producer room should feel like the back of the client's room. */
body.ops::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 9; opacity: .035;
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}

/* The one thing on these pages that is somebody else's words has to be
 * copyable, whatever the chrome does. */
.verbatim, .changed, input, textarea, [contenteditable] {
  -webkit-user-select: text; user-select: text;
}
[contenteditable] { caret-color: var(--acc2); }
::selection { background: var(--sel-bg); }
button:focus-visible, a:focus-visible, [contenteditable]:focus-visible {
  outline: var(--ring-outline); outline-offset: 1px;
}
button {
  font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease), color var(--fast) var(--ease), transform 70ms ease;
}
button:active { transform: translateY(.5px); }
input, textarea { font: inherit; }
/* --ink4 keeps only --bg and --void; the composer and the seat form sit on
 * --surf, where it is under the floor. RULED 2026-09-10. */
input::placeholder, textarea::placeholder { color: var(--ink3); }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
svg { flex: none; display: block; }
img { display: block; }
h2 { font: var(--role-section); color: var(--ink); }
h3 { font: var(--role-section); color: var(--ink); }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--rule2); border-radius: 4px; } /* R43: named recipe, not a box: scrollbar thumb */
::-webkit-scrollbar-track { background: transparent; }
@keyframes cal-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes cal-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  55% { transform: translateX(4px); }
  80% { transform: translateX(-2px); }
}
.cal-shake { animation: cal-shake .32s; }

.sr-only, .skip:not(:focus) {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip:focus {
  position: fixed; inset: 8px auto auto 8px; padding: 8px 12px; z-index: 90;
  background: var(--surf2); color: var(--ink); border-radius: var(--r9);
  font: var(--role-current);
  font-size: var(--role-row-13);
  line-height: 1;
}

/* The one glyph recipe: a filled shape, sized by whatever carries it, and
 * never given a colour of its own. David, 10 September 2026: icons are solid,
 * never wireframes, so the weight lives in the path and not in a stroke.
 * `.sm` is the small pair (the caret, the tick, the cross); it changes nothing
 * here now that the weight is drawn, and stays as the hook the markup uses. */
.icon { fill: currentColor; }
.icon.sm { fill: currentColor; }

/* ------------------------------------------------------------------ topbar */

/* Whose product this is, where you are in it, and who you are on it. Three
 * columns: the wordmark and the scope at the left, the four destinations in
 * the centre where the system puts StageNav, the account at the right.
 *
 * R38 (David, 12 September 2026, amending R28), F15: the bar is its own inset
 * panel, the locked room-topbar part's own recipe lifted rather than redrawn
 * (R41, docs/design/parts/room-topbar.html, .tb): 8px from the window's edge
 * and the panel below, the panel tone, r13, 60 tall, and no rule under it --
 * surfaces separate by the ramp and by air, never by a border (R10). */
.bar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  height: 60px; min-width: 0;
  margin: 8px 8px 0; padding: 0 16px; background: var(--panel); border-radius: var(--r13);
  position: relative; z-index: 3;
}
.bar-l { display: flex; align-items: center; min-width: 0; }
.bar-r { display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-width: 0; position: relative; }
.mark { display: block; height: 15px; width: auto; fill: var(--ink); filter: drop-shadow(0 0 14px color-mix(in srgb, var(--ink) 14%, transparent)); }
.sep { flex: none; width: 1px; height: 16px; margin: 0 16px; background: var(--rule2); }
.scope { font: var(--role-section); color: var(--ink2); white-space: nowrap; }

/* Four words. The current one is 600 in ink and nothing else moves: no
 * underline says "on", not the accent's and not anyone's (R7, 10 September
 * 2026 evening; F16). */
.nav { display: flex; align-items: center; gap: 26px; height: 60px; }
.nav-item {
  display: inline-flex; align-items: center; gap: 7px; height: 60px;
  font: var(--role-secondary);
  line-height: 1; color: var(--ink3); white-space: nowrap;
  transition: color var(--fast) var(--ease);
}
.nav-item:hover { color: var(--ink2); }
.nav-item[aria-current="page"] { color: var(--ink); font-weight: var(--role-current-weight); }
/* A dot when something waits on the producer reading the bar, never a numeral
 * (R14, R31; David, 14 September 2026: "the counts, which are another
 * violation"). The number lives on the desk, where a person acts on it (R48).
 * The dot is the drawing's own mark: 6px of gold beside the word. */
.nav-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--att); } /* R43: named recipe, not a box: the nav's wait dot */

.me {
  display: inline-flex; align-items: center; gap: 9px; height: 38px;
  padding: 0 8px 0 5px; border-radius: var(--r9); max-width: 260px;
}
/* R67, David, 13 September 2026: no fill behind a control at rest, under the
   pointer, or while what it opens stands. The name's ink steps up instead. */
.me:hover .me-name { color: var(--ink2); }
.me[aria-expanded="true"] .me-name { color: var(--ink2); }
.me-name { font: var(--role-secondary); line-height: 1; color: var(--ink3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.me .icon { width: 16px; height: 16px; color: var(--ink4); }
.sync { font: var(--role-secondary); color: var(--ink3); white-space: nowrap; }
.sync-pending { color: var(--ink2); } /* a mark on the wire waits on the network, not on you: ink */
.pop-account { top: 46px; right: 0; left: auto; width: 280px; min-width: 0; padding: 12px; }
.pop-who { display: flex; align-items: center; height: 30px; margin-bottom: 6px; padding: 0 8px; font: var(--role-secondary); color: var(--ink3); overflow-wrap: anywhere; }
.pop-account form { display: block; }

/* A person's disc. The wheel's eight slots leave the violet band empty, so a
 * person can never be read as a control. */
.avatar {
  display: grid; place-items: center; flex: none; width: 28px; height: 28px;
  border-radius: 50%; color: var(--white); font: var(--role-current); font-size: var(--role-row-13); line-height: 1;
} /* R43: named recipe, not a box: avatar disc */
.pc-1 { background: linear-gradient(var(--pc1)); }
.pc-2 { background: linear-gradient(var(--pc2)); }
.pc-3 { background: linear-gradient(var(--pc3)); }
.pc-4 { background: linear-gradient(var(--pc4)); }
.pc-5 { background: linear-gradient(var(--pc5)); }
.pc-6 { background: linear-gradient(var(--pc6)); }
.pc-7 { background: linear-gradient(var(--pc7)); }
.pc-8 { background: linear-gradient(var(--pc8)); }
.avatar.is-pending { background: var(--surf2); color: var(--ink3); }
.avatar.is-pending .icon { width: 14px; height: 14px; }

/* -------------------------------------------------------------------- row 2 */

/* An action bar, never a title bar. It carries what you can do on this screen,
 * and on a screen that is one object the way back and that object's name.
 * The same inset panel the topbar is (R38 amending R28, F15): the panel tone,
 * r13, an 8px gutter from the bar above and the window's edges, no rule. */
.r2 { margin: 8px 8px 0; background: var(--panel); border-radius: var(--r13); position: relative; z-index: 2; }
.r2-in {
  display: flex; align-items: center; gap: 12px; min-height: 60px;
  width: 100%; max-width: 1168px; margin: 0 auto; padding: 0 24px; position: relative;
}
.r2 + .r2 { display: none; }
.back {
  display: grid; place-items: center; flex: none; width: 34px; height: 34px;
  margin-left: -8px; border-radius: var(--r9); color: var(--ink3);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.back .icon { width: 18px; height: 18px; }
.back:hover { color: var(--ink); }
.r2-title { min-width: 0; font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); letter-spacing: var(--role-tracking); overflow-wrap: anywhere; }
.r2-when { margin-left: auto; font: var(--role-secondary); color: var(--ink3); white-space: nowrap; }
.r2-menu { margin-left: auto; }
.pop-person { top: 46px; right: 24px; }

/* ---------------------------------------------------------------------- page */

.page {
  max-width: 1168px; margin: 0 auto;
  padding: 24px var(--gutter) calc(var(--walk) + 24px + env(safe-area-inset-bottom));
}
.escalations-page, .history-page, .keys-page { max-width: 768px; }

/* ------------------------------------------------------------------ controls */

/* Cream, spent once per surface, and flat: tone is the voice, never elevation.
 * A filled control darkens on hover, always. The primary and its tonal shadow
 * are word controls at the 44 a thumb clears; the glyph controls below them
 * are the room's shared one, an 18px glyph in a 34px target (R11, R41, F31,
 * app.css's .ibtn, lifted not redrawn). */
.cream {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 20px; border-radius: var(--r9);
  background: var(--ink); color: var(--panel); font: var(--role-current); font-size: var(--role-row-13);
}
.cream:hover { background: var(--cream-hover); }
.cream:active { background: var(--cream-active); }
.cream .icon { width: 18px; height: 18px; }
.tonal {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 16px; border-radius: var(--r9);
  background: var(--surf2); color: var(--ink2); font: var(--role-current); font-size: var(--role-row-13); line-height: 1;
}
.tonal:hover { background: var(--lift2); color: var(--ink); }
.tonal .icon { width: 18px; height: 18px; }
.quiet {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-width: 44px; min-height: 44px; padding: 0 12px;
  border-radius: var(--r9); font: var(--role-secondary); line-height: 1; color: var(--ink3);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.quiet .icon { width: 18px; height: 18px; }
.quiet:hover { color: var(--ink); }
/* One size, one grey, unboxed. Light on hover, never a border. The shared
 * room control: an 18px glyph in a 34px target at r9 (R11, R41, F31). */
.ghost {
  display: grid; place-items: center; flex: none; width: 34px; height: 34px;
  border-radius: var(--r9); color: var(--ink4);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.ghost .icon { width: 18px; height: 18px; }
.ghost:hover { color: var(--ink); }
/* A modal is its own surface and its primary is iris: the named exception the
 * Modal recipe carries, and legal only at this chroma, where white on the fill
 * measures 4.89:1 and darkens to 6.20 and 7.66. */
.violet {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 20px; border-radius: var(--r9);
  background: var(--acc); color: var(--white); font: var(--role-current); font-size: var(--role-row-13);
}
.violet:hover { background: var(--acc-hover); }
.violet:active { background: var(--acc-active); }
.violet .icon { width: 18px; height: 18px; }

/* The state words: green settled, gold waiting on the producer reading them,
 * plain ink for a state that waits on somebody else, --ink4 over. */
.state { font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); white-space: nowrap; }
.state-ok { color: var(--ok); }
.state-att { color: var(--att); }
.state-over { color: var(--ink4); }
/* A record of a decision already taken (sent back, regenerate, replace) is
 * not an ask on anybody, so there is no gold tone here: green for the settled
 * good ones and --ink3 for the rest (gold means one thing, 10 Sep 2026). */
.mark-tag { font: var(--role-current); font-size: var(--role-row-13); white-space: nowrap; }
.mark-ok { color: var(--ok); }
.mark-over { color: var(--ink3); }

/* ONE TALLY: the glyph is the label, the text beside it is the value, and the
 * colour obeys the system's rule about which of the three hues may carry one.
 * `.sm` is the one run that is meta end to end, the scope. */
.tally { display: inline-flex; align-items: center; gap: 6px; font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.tally .icon { width: 14px; height: 14px; color: var(--ink3); }
.tally.sm { font: var(--role-secondary); color: var(--ink3); }
.tally.sm .icon { width: 13px; height: 13px; }
.tally.is-att, .tally.is-att .icon { color: var(--att); } /* only what waits on us; a wait on them takes no tone */
.tally.is-ok .icon { color: var(--ok); }
.tallies { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 14px; min-width: 0; }
.tallies:empty { display: none; }
.scope-role { font: var(--role-secondary); color: var(--ink3); }
.row-glyph { display: inline-flex; color: var(--ink3); }
.row-glyph .icon { width: 15px; height: 15px; }

/* ONE BAR: 6px, one share, green, with the count above it at size in --ink.
 * A second share would be a second line, never a second segment. */
.progress-track { display: flex; width: 100%; height: 6px; border-radius: 999px; background: var(--track); overflow: hidden; } /* R43: named recipe, not a box: pill */
.progress-track i { display: block; height: 100%; }
.progress-done { background: var(--ok); border-radius: 999px; } /* R43: named recipe, not a box: pill */
.progress-tally { flex: none; white-space: nowrap; }

/* ONE FOLD: a closed line at the foot, never a box of nothing. */
.fold {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px;
  padding: 0 10px 0 4px; border-radius: var(--r9);
  font: var(--role-secondary);
  line-height: 1; color: var(--ink3);
}
.fold:hover { color: var(--ink2); }
/* The fold's chevron: the system's solid one at the one glyph size, turned
 * when the fold is closed, never a scaled-down arrow of its own (David,
 * 13 September 2026). */
.fold .icon { width: 16px; height: 16px; color: var(--ink4); transition: transform var(--fast) var(--ease); }
.fold[aria-expanded="false"] .icon { transform: rotate(-90deg); }
.fold b { font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.fold-line { margin-top: 20px; }
.fold-line.is-centred { display: flex; justify-content: center; }

/* An empty state is a state, not an instruction. */
.empty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 96px 20px 24px; }
.empty .icon { width: 16px; height: 16px; color: var(--ink4); }
.empty p { font: var(--role-section); color: var(--ink3); }

/* A read-only note about the page itself: the queue's age, a rehearsal room,
 * evidence held elsewhere. It waits on nobody, so it is a lift and one line of
 * ink rather than gold (gold means one thing, 10 Sep 2026). No border (R10,
 * F20): the lift is what separates it. */
.banner {
  display: flex; align-items: center; gap: 8px; margin-bottom: 16px;
  padding: 12px 16px; border-radius: var(--r9);
  background: var(--lift);
  color: var(--ink2); font: var(--role-current); font-size: var(--role-row-13);
}

/* -------------------------------------------------- the dock and its popovers */

/* A view control: a glyph, its value, and its word on the tooltip. The label
 * came off in the quiet pass of 10 September; what is left is the value, and
 * the value is what a view control is for. */
.tool {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 9px;
  border-radius: var(--r9); font: var(--role-secondary); line-height: 1; color: var(--ink3); white-space: nowrap;
}
.tool:hover { color: var(--ink2); }
.tool[aria-expanded="true"] { color: var(--ink); }
.tool b { min-width: 0; font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
.tool .cnt { font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.tool .icon { width: 14px; height: 14px; color: var(--ink4); }
/* The chevron beside a tool's value is the system's solid chevron at the one
 * glyph size, never a smaller arrow of its own (David, 13 September 2026, on
 * the one beside Sorted by: "This tiny arrow looks awful"). */
.tool .icon.sm { width: 16px; height: 16px; }
.tool.only { width: 34px; padding: 0; justify-content: center; }
.tool.only .icon { width: 15px; height: 15px; }
.tool-split { flex: none; width: 1px; height: 16px; margin: 0 6px; background: var(--rule); }

.pop {
  position: absolute; z-index: 8; top: 44px; left: 0; min-width: 220px; max-width: 320px;
  background: var(--panel); border-radius: var(--r13);
  padding: 10px; box-shadow: var(--shadow-menu);
}
.pop[hidden] { display: none; }
.pop h4 { padding: 2px 6px 8px; font: var(--role-section); color: var(--ink); }
.pop-item {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 32px; padding: 0 8px;
  border-radius: var(--r6); font: var(--role-current); font-size: var(--role-row-13); line-height: 1; color: var(--ink2); text-align: left;
}
.pop-item:hover { background: var(--surf); color: var(--ink); }
/* The chosen word and its tick are ink, never the accent (R6, F19): a tick in
 * ink, or one neutral step, and grey hover never sits beside purple. */
.pop-item[aria-checked="true"] { color: var(--ink); }
.pop-item .cnt { margin-left: auto; font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.pop-item .icon { width: 16px; height: 16px; }
.pop-item .tick { opacity: 0; color: var(--ink); }
.pop-item[aria-checked="true"] .tick { opacity: 1; }
.pop-scope { margin-left: auto; font: var(--role-secondary); line-height: 1; color: var(--ink3); }
/* R40 allows the one hairline of the ramp before a destructive act; a facet
 * group separates by its heading and its space, so nothing draws between
 * them (F20, R10). */
.pop-sep { height: 1px; margin: 8px 2px; background: var(--rule); }
.pop-row { display: flex; align-items: center; gap: 12px; min-height: 36px; padding: 0 6px; font: var(--role-secondary); line-height: 1; color: var(--ink3); }
.pop-row .seg, .pop-row .sw { margin-left: auto; }
.pop-form { display: block; }
.pop-filter { width: 268px; }
.pop-appearance { width: 288px; left: 305px; }
.pop-fields { left: 620px; }
.pop-sort { left: 700px; }

/* Email cadence is one menu grid. Daily adds two choice rows; neither value
 * is typed into a field. The padding is restated here because the base .pop
 * rule below sets 10 and would win the cascade (it is later in the file),
 * which sat every word 2 inside the drawing's own edge: the label began at
 * 18 and the controls ended at 262, against the drawn 20 and 260. */
.pop.pop-account { top: 53px; right: 0; left: auto; padding: 12px; }
.cadence-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; height: 34px; padding: 0 8px; border-radius: var(--r6); }
button.cadence-row:hover { background: var(--hov); }
.cadence-label { flex: none; font: var(--role-section); font-size: var(--role-row-13); line-height: 1; color: var(--ink3); }
.cadence-value { display: inline-flex; align-items: center; gap: 7px; font: var(--role-current); font-size: var(--role-row-13); line-height: 1; color: var(--ink); }
.cadence-value .icon { width: 13px; height: 13px; color: var(--ink4); }
.cadence-segments { display: inline-flex; flex: none; gap: 2px; padding: 3px; border-radius: var(--r9); background: var(--bg); }
.cadence-segments button { height: 26px; padding: 0 10px; border-radius: var(--r6); font: var(--role-secondary); line-height: 1; color: var(--ink3); }
.cadence-segments button[aria-checked="true"] { background: var(--surf2); color: var(--ink); font-weight: var(--role-control-weight); }
.cadence-segments button:hover { color: var(--ink2); }
.cadence-gap { height: 10px; }
.pop-account .pop-item { height: 34px; padding: 0 8px; }
.cadence-list { position: absolute; right: calc(100% + 8px); width: 140px; padding: 6px; background: var(--lift2); border-radius: var(--r13); box-shadow: var(--shadow-menu); }
.cadence-list[data-cadence-list="at"] { top: 18px; width: 108px; }
.cadence-list[data-cadence-list="zone"] { top: 82px; width: 140px; }
.cadence-list-scroll { max-height: 240px; overflow-y: auto; scrollbar-width: thin; }
.cadence-list-row { display: flex; align-items: center; gap: 8px; width: 100%; height: 30px; padding: 0 8px 0 6px; border-radius: var(--r6); font: var(--role-current); font-size: var(--role-row-13); line-height: 1; color: var(--ink2); }
.cadence-list-row:hover { background: var(--hov); }
.cadence-list-row .icon { width: 13px; height: 13px; color: var(--ink); opacity: 0; }
.cadence-list-row[aria-selected="true"] { color: var(--ink); font-weight: var(--role-current-weight); }
.cadence-list-row[aria-selected="true"] .icon { opacity: 1; }

/* The segmented: the track is a surface one step down, which says what the
 * 1px line used to (R10, F20), the room's own Appearance control lifted. */
.seg { display: inline-flex; flex: none; padding: 3px; gap: 2px; border-radius: var(--r9); background: var(--bg); }
.seg > * { display: grid; place-items: center; min-height: 26px; padding: 0 11px; border-radius: var(--r6); font: var(--role-secondary); line-height: 1; color: var(--ink3); background: transparent; }
.seg .icon { width: 15px; height: 15px; }
/* The chosen segment is one neutral step up, its label in ink, never an
 * accent fill: the selection ruling of 10 and 11 September 2026 holds for a
 * segment as for a row, and the room's own Layout control never filled
 * (David, 13 September 2026). */
.seg [aria-pressed="true"] { background: var(--hov2); color: var(--ink); }

.sw { position: relative; display: block; flex: none; width: 40px; height: 22px; border-radius: var(--r13); background: var(--surf2); }
.sw i { position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: var(--white); transition: transform var(--fast) var(--ease); } /* R43: named recipe, not a box: switch knob */
.sw[aria-pressed="true"], .sw.is-fixed { background: var(--acc); }
.sw[aria-pressed="true"] i, .sw.is-fixed i { transform: translateX(18px); }

/* ONE DISCLOSURE: a chevron at the left of the thing it opens, inside the
 * heading's own button, rotated when closed. */
.disc {
  display: inline-flex; align-items: center; gap: 9px; min-height: 34px;
  margin-left: -6px; padding: 0 6px; border-radius: var(--r6); color: inherit; text-align: left;
}
/* R67: the disclosure is a word button, so its hover is the ink, not a plate. */
.disc > .chev { width: 16px; height: 16px; color: var(--ink4); transition: transform var(--fast) var(--ease); }
.disc[aria-expanded="false"] > .chev { transform: rotate(-90deg); }
.disc b { font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }

/* ------------------------------------------------------------------- people */

.people-page, .person-page { max-width: 1168px; }
.ops-people .bar { height: 56px; margin-bottom: 0; padding: 0 20px; }
.ops-people .mark { width: 84px; height: 25px; }
.ops-people .sep { height: 20px; margin: 0 20px; }
.ops-people .me .avatar { width: 26px; height: 26px; font-size: var(--role-row-12); }
/* 100dvh - 80: 64 of bar and margin above, and the 8 gutter below, so the
 * panel never touches the window's foot (R28/R38; the drawing's stage ends
 * at 892 on a 900 window, not 900). */
.ops-people .page.people-page { width: auto; max-width: none; min-height: calc(100dvh - 80px); margin: 8px; padding: 24px; background: var(--panel); border-radius: var(--r13); }
.ops-people .people-room { position: relative; }
.ops-people .room-head { align-items: center; gap: 12px; min-height: 28px; }
.people-room-name { display: inline-flex; align-items: center; gap: 7px; height: 28px; margin-left: -8px; padding: 0 8px; border-radius: var(--r9); font: var(--role-current); font-size: var(--role-row-15); line-height: 1; color: var(--ink); }
.people-room-name:hover { background: var(--hov); }
.people-room-name .icon { width: 13px; height: 13px; color: var(--ink4); }
.ops-people .room-line { margin-top: 12px; font: var(--role-secondary); line-height: 1; color: var(--ink3); }
.people-room-value { margin-top: 12px; font: var(--role-current); font-size: var(--role-row-13); line-height: 1; color: var(--ink); }
.ops-people .room-bar { margin-top: 8px; }
.ops-people .room-bar .progress-track { width: 240px; }
.room-head { display: flex; align-items: baseline; gap: 16px; }
.room-head h2 { font: var(--type-title); color: var(--ink); letter-spacing: var(--role-title-tracking); }
.room-head + .room-head, .people-room + .room-head { margin-top: 26px; }
.people-room + .people-room { margin-top: 28px; }
.room-wait { margin-left: auto; white-space: nowrap; }
.room-line { margin-top: 8px; }
.room-bar { margin-top: 14px; display: grid; gap: 10px; justify-items: start; }
.room-bar .progress-track { width: 320px; }
.room-open[hidden] { display: none; }

/* THE PEOPLE ARE ROWS IN SPACE (R65, David, 13 September 2026: "bunched up
 * rows with the same background that looks like a hover, is very wrong"; F17).
 * No card ground, no gradient, no lift: a row at rest has no fill of its own,
 * rows are held apart by their spacing and the ink of their words, and the
 * one fill on this page means the pointer is over a row. The 2px gap the page
 * once carried bunched them; 10 is the desk's own figure between rows. The
 * six count icons are words (R64's second word), so nothing here draws a
 * tally's glyph. */
.people { margin-top: 22px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; align-items: stretch; }
.person-row {
  display: grid; grid-template-columns: 36px minmax(0, 1fr) 24px; grid-template-rows: auto auto 1fr auto;
  column-gap: 12px; align-items: start; padding: 16px; min-width: 0; height: 224px;
  border-radius: var(--r13); background: var(--surf); color: var(--ink);
}
.person-row:hover { background: var(--surf2); }
.people-card-avatar { width: 36px; height: 36px; font-size: var(--role-row-12); }
.person-row .prow-who { min-width: 0; align-self: start; }
.person-row .prow-who strong { font: var(--role-current); font-size: var(--role-row-15); line-height: 20px; }
.person-row .prow-who span { margin-top: 2px; font: var(--role-current); font-size: var(--role-row-13); line-height: 18px; }
.person-row .prow-menu { grid-column: 3; grid-row: 1; width: 24px; height: 24px; margin: -2px -4px 0 0; opacity: 1; }
.person-row .prow-menu .icon { width: 16px; height: 16px; }
.person-row .prow-facts { grid-column: 1 / -1; display: block; min-width: 0; margin-top: 14px; }
.person-row .prow-line { display: block; margin-top: 2px; font: var(--role-secondary); line-height: 18px; color: var(--ink3); white-space: nowrap; overflow: visible; text-overflow: clip; }
.person-row .prow-line:first-child { margin-top: 0; }
.person-row .people-card-value { margin-top: 8px; color: var(--ink); }
.person-row .people-card-value .progress-track { display: block; width: 100%; margin-top: 8px; }
.person-row .prow-end { grid-column: 1 / -1; align-self: end; justify-self: start; padding-top: 14px; }
.person-row .prow-end:empty { display: none; }
.person-row .state { line-height: 18px; }
.person-row .avatar { width: 36px; height: 36px; font-size: var(--role-row-13); }
.prow-who { min-width: 0; display: grid; gap: 2px; }
.prow-who strong { font: var(--role-current); font-size: var(--role-row-15); line-height: 1.3; letter-spacing: var(--role-tracking); color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.prow-who span { font: var(--role-secondary); color: var(--ink3); min-width: 0; overflow-wrap: anywhere; }
.prow-facts { min-width: 0; display: grid; gap: 3px; justify-items: start; }
.prow-line { font: var(--role-secondary); line-height: 1.45; color: var(--ink3); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prow-line b { font-weight: var(--role-current-weight); color: var(--ink); }
.prow-end { display: flex; align-items: center; gap: 10px; }
/* The row's menu stands at rest only under the pointer, the way the drawing
 * draws the per-card overflow. */
.prow-menu { opacity: 0; transition: opacity var(--fast) var(--ease); }
.person-row:hover .prow-menu, .prow-menu:focus-visible { opacity: 1; }

/* --------------------------------------------------- the container card
 * A leaf card is a picture. A container card is a thing that holds other
 * things, and its mosaic is the only thing that says so. The folder tab it
 * carried on the morning of 10 September is struck: a tab beside the mosaic
 * said it twice. Shared with the Studio. */
.rooms { margin-top: 20px; display: grid; gap: 14px; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: stretch; }
.rooms > li { display: grid; }
.ccard { display: flex; flex-direction: column; color: var(--ink); transition: transform var(--slow) var(--ease); }
.ccard:hover { transform: translateY(-2px); }
.ccard-body {
  position: relative; isolation: isolate; flex: 1; display: flex; flex-direction: column;
  border-radius: var(--r13); background: var(--lift2);
  transition: box-shadow var(--slow) var(--ease);
}
.ccard-body::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: linear-gradient(180deg, var(--lift2), var(--lift));
  transition: opacity var(--slow) var(--ease);
} /* R43: named recipe, not a box: gradient layer takes its box radius */
.ccard:hover .ccard-body { box-shadow: var(--shadow-card); }
.ccard:hover .ccard-body::before { opacity: 0; }
/* One large and two small. The geometry is what makes both the large well and
 * the two small ones come out at exactly 4:5. */
.ccard-mosaic {
  display: grid; gap: 6px; aspect-ratio: 17 / 14; margin: 12px 12px 4px;
  grid-template-columns: minmax(0, 2.045fr) minmax(0, 1fr);
  grid-template-rows: repeat(2, minmax(0, 1fr));
}
/* A slot is filled edge to edge: covered and cropped to the slot, centred,
 * never pillar- or letterboxed. A VIEWER pane is the other case and still
 * contains, touching two edges. RULED 10 September 2026. */
.ccard-well {
  min-width: 0; min-height: 0; border-radius: var(--r9); background-color: var(--stage);
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
.ccard-well:first-child { grid-row: 1 / span 2; }
.ccard-foot { display: flex; align-items: center; gap: 10px; padding: 8px 16px 16px; min-height: 26px; margin-top: auto; }
/* The foot is the name alone (R14; David, 10 September 2026, on the counts
 * beside names: "feels very AI-default to me"): a number returns to a card
 * only as a state somebody must act on, never as a running total. */
.ccard-foot strong { min-width: 0; font: var(--type-title); letter-spacing: var(--role-title-tracking); color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ccard-mark { flex: none; font: var(--role-secondary); line-height: 1; color: var(--ink3); }
.ccard-menu {
  margin-left: auto; display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: var(--r6); color: var(--ink3);
}
.ccard-menu .icon { width: 15px; height: 15px; }
.ccard:hover .ccard-menu { color: var(--ink2); }
.ccard-menu:hover { background: var(--surf2); color: var(--ink); }

/* ------------------------------------------------------------ the empty cover
 * BEFORE A THING HAS A PICTURE OF ITS OWN ITS WELL IS THE CARD'S OWN SURFACE
 * ONE STEP DARKER, AND NOTHING ELSE. RULED BY DAVID, 10 September 2026, the
 * same day, retiring the lift pictures the wells wore: "We really can't use
 * these over complicated placeholder graphics." No picture, no gradient, no
 * blurred tone pool, no hash choosing between them, nothing on it: a grid of
 * empty wells reads as empty, and the real pictures stay the only colour in
 * it. Shared with the Studio. */
.is-empty { background: var(--lift); }
.well.is-empty { background: var(--stage); }

/* What the loop's mail said, with a control to copy it: mail to a client does
 * not always arrive, so the producer holds the words to pass on another way. */
.seat-note { display: grid; gap: 10px; justify-items: start; margin-bottom: 20px; padding: 16px; background: var(--panel); border-radius: var(--r13); color: var(--ink2); font: var(--role-secondary); }
.seat-note.is-error { color: var(--danger); } /* an error is a refusal, not a state: rose, never gold */
.seat-note .mc-mail { width: 100%; }

/* ---------------------------------------- the members panel and the modal */

.scrim { position: fixed; inset: 0; z-index: 70; background: var(--scrim); }
.scrim[hidden], .panel[hidden], .modal[hidden] { display: none; }

.panel {
  position: fixed; z-index: 71; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 32px)); max-height: 78%; display: grid; grid-template-rows: auto minmax(0, 1fr);
  background: var(--panel); border-radius: var(--r13);
  box-shadow: var(--shadow-menu);
}
/* No rule under the title row (R10, F20): the body's own ground starts where
 * the title row's air ends, and space does the separating. */
.panel-top { display: flex; align-items: center; gap: 10px; padding: 14px 12px 14px 20px; }
.panel-top h3 { flex: 1; min-width: 0; font: var(--role-current); font-size: var(--role-row-15); line-height: 1.3; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.panel-add { min-height: 34px; min-width: 0; padding: 0 12px; }
.panel-body { overflow: auto; padding: 16px 20px 20px; }
.panel-find {
  width: 100%; height: 44px; padding: 0 14px;
  border: 1px solid var(--rule2); border-radius: var(--r9); background: var(--bg);
  color: var(--ink); font: var(--role-secondary); line-height: 1;
}
.panel-find:focus-visible { outline: 0; border-color: var(--acc); }
.panel-restrict { margin-top: 16px; padding: 14px; background: var(--bg); border-radius: var(--r13); }
.panel-restrict .pop-row { padding: 0; }
.panel-note { margin-top: 8px; font: var(--role-secondary); line-height: 1.5; color: var(--ink3); text-wrap: pretty; }
.panel-h { margin: 0 0 8px; font: var(--role-section); color: var(--ink); }
.panel-body > .panel-h { margin-top: 20px; }
.mem-list { display: grid; }
/* Rows in space: no rule between people (R10, R65, F18), in the members panel
 * and on the producers list alike. The spacing and the ink of the words do
 * the separating. */
.mem-row { display: flex; align-items: center; gap: 10px; min-height: 56px; padding: 8px 0; position: relative; }
.mem-who { flex: 1; min-width: 0; display: grid; gap: 2px; }
.mem-who strong { font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); }
.mem-who span { font: var(--role-secondary); color: var(--ink3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mem-pending { font: var(--role-secondary); line-height: 1.3; font-style: normal; color: var(--ink3); } /* waits on them to arrive, not on you: ink */
.mem-access {
  flex: none; display: inline-flex; align-items: center; gap: 12px; min-height: 34px; max-width: 250px;
  padding: 0 8px 0 10px; border-radius: var(--r6); background: var(--surf);
  font: var(--role-current);
  font-size: var(--role-row-13);
  line-height: 1; color: var(--ink2); white-space: nowrap;
}
.mem-access:hover { background: var(--surf2); color: var(--ink); }
.mem-access .tally { min-width: 0; }
/* The producers' own rows on People: the zone and the cadence choice, a fact
 * and not a control, at the right of the row the way a member's access is. */
.people-producers-heading { margin-top: 36px; font: var(--role-current); font-size: var(--role-row-15); line-height: 1; }
.people-producers { margin-top: 10px; }
.people-producers .mem-row { min-height: 56px; margin: 0 -8px; padding: 0 8px; border-radius: var(--r9); }
.people-producers .mem-row:hover { background: var(--hov); }
.people-producers .mem-who strong { font-size: var(--role-row-15); }
.mem-cadence { display: inline-flex; align-items: center; gap: 7px; flex: none; height: 30px; padding: 0 8px; border-radius: var(--r9); color: var(--ink); font: var(--role-current); font-size: var(--role-row-13); line-height: 1; white-space: nowrap; }
.mem-cadence:hover { background: var(--hov); }
.mem-cadence .icon { width: 13px; height: 13px; color: var(--ink4); }
.mem-access .icon { width: 13px; height: 13px; color: var(--ink3); }
.pop-access { top: 44px; right: 0; left: auto; }

.modal {
  position: fixed; z-index: 71; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(880px, calc(100vw - 32px)); max-height: 78%;
  background: var(--panel); border-radius: var(--r13);
  box-shadow: var(--shadow-menu);
}
.modal-form { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; max-height: inherit; height: 100%; }
/* No rules in the modal's chrome (R10, F20): the title row, the body and the
 * foot separate by their own air. */
.modal-top { display: flex; align-items: center; gap: 10px; padding: 14px 12px 14px 20px; }
.modal-top h3 { flex: 1; min-width: 0; font: var(--role-current); font-size: var(--role-row-15); line-height: 1.3; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.modal-body { overflow: auto; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 28px; padding: 16px 20px 20px; }
.modal-foot { display: flex; justify-content: flex-end; padding: 14px 20px; }
.lcards { display: grid; gap: 8px; }
.lcard {
  position: relative; isolation: isolate; display: grid; gap: 3px; width: 100%;
  padding: 12px 14px; border-radius: var(--r13); background: var(--lift2); text-align: left; cursor: pointer;
}
.lcard::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: linear-gradient(180deg, var(--lift2), var(--lift)); transition: opacity var(--slow) var(--ease); } /* R43: named recipe, not a box: gradient layer takes its box radius */
.lcard:hover::before { opacity: 0; }
.lcard strong { font: var(--type-title); letter-spacing: var(--role-title-tracking); color: var(--ink); }
.lcard .tallies { gap: 2px 12px; margin: 2px 0 1px; }
.lcard small { font: var(--role-secondary); color: var(--ink3); }
.lcard.is-on, .lcard:has(input:checked) { box-shadow: var(--ring-quiet); }
.mc-head { display: flex; align-items: center; gap: 8px; }
.mc-head .panel-h { flex: 1; }
.mc-mail { padding: 14px; border-radius: var(--r13); background: var(--stage); display: grid; gap: 8px; }
.mc-mail p { font: var(--role-secondary); line-height: 1.6; color: var(--ink2); overflow-wrap: anywhere; }
.mc-mail b { font-weight: var(--role-current-weight); color: var(--ink); }

/* ------------------------------------------------------------------- person */

.person-head { display: flex; align-items: flex-start; gap: 14px; }
.person-head .avatar { width: 44px; height: 44px; font-size: var(--role-row-13); }
.person-id { min-width: 0; display: grid; gap: 4px; }
.person-id h2 { font: var(--role-current); font-size: var(--role-row-16); line-height: 1.2; color: var(--ink); letter-spacing: var(--role-tracking); }
.person-id > span { font: var(--role-secondary); color: var(--ink3); }
.person-att { margin-left: auto; display: grid; gap: 7px; justify-items: end; }
.person-bar { margin-top: 20px; display: grid; gap: 10px; justify-items: start; }
.person-bar .progress-track { width: 320px; }
.person-cols { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 28px; align-items: start; }
.person-col { min-width: 0; }
.person-col .section:first-child { margin-top: 24px; }
.section { margin-top: 28px; }
.section h2 { margin: 0; }
.section .disc { margin-bottom: 8px; }

/* A panel carries no padding; its rows do. */
.list { background: var(--panel); border-radius: var(--r13); padding: 4px; }
.list[hidden] { display: none; }
.row {
  display: grid; align-items: center; gap: 12px; padding: 12px; border-radius: var(--r9);
  color: inherit; transition: background var(--fast) var(--ease);
}
a.row:hover { background: var(--surf); }
/* A 48px slot, covered: a 1.91:1 still contained in it came out as a 48 x 25
 * strip with bands above and below, which is the letterbox the ruling names. */
.well {
  flex: none; display: block; width: 48px; height: 48px;
  border-radius: var(--r6); background-color: var(--stage); overflow: hidden;
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
.cell-row { grid-template-columns: 48px minmax(0, 1fr) auto; }
.cell-name { min-width: 0; display: grid; gap: 3px; }
.cell-name strong { font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.thread-row { grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
.thread-row .verbatim { font: var(--role-body); color: var(--ink); }
.thread-row small { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 12px; margin-top: 6px; font: var(--role-secondary); color: var(--ink3); }
.sit-row { grid-template-columns: minmax(0, 1fr) auto; }
.sit-row strong { font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); }
.sit-row > span:last-child { font: var(--role-secondary); color: var(--ink3); }
.sit-row > span:first-child { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; }
.people-empty { padding: 14px 12px; color: var(--ink3); font: var(--role-secondary); }

/* ------------------------------------------------------------------ changes */

.day { margin-top: 26px; }
.day:first-of-type { margin-top: 0; }
.chg-row { grid-template-columns: 48px minmax(0, 1fr) auto; align-items: start; }
.chg-body { min-width: 0; display: grid; gap: 4px; }
.chg-title { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.chg-title strong { font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.chg-title .tallies { flex: none; }
.chg-what { font: var(--role-secondary); line-height: 1.5; color: var(--ink); text-wrap: pretty; }
/* Who did it is a mark, not a line: the sparkle is the system's own AI glyph
 * and an avatar is a person. The sentence above already names them and the
 * tooltip carries the line. */
.chg-end { display: flex; align-items: center; gap: 12px; padding-top: 1px; }
.chg-actor { display: inline-flex; align-items: center; gap: 6px; color: var(--acc2); }
.chg-actor .icon { width: 14px; height: 14px; }
.chg-actor .avatar { width: 24px; height: 24px; font-size: var(--role-row-13); }
.chg-when { font: var(--role-secondary); color: var(--ink3); white-space: nowrap; }

/* --------------------------------------------------------------------- keys */

.keys-section + .keys-section { margin-top: 28px; }
.keys-section .disc { margin-bottom: 10px; }
.keys { display: grid; gap: 10px; }
.keys[hidden] { display: none; }
.key { display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr) 44px; align-items: start; padding: 16px; background: var(--panel); border-radius: var(--r13); }
.key-head { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 14px; min-width: 0; }
.key-head strong { font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); }
.key-for { grid-column: 1; font: var(--role-secondary); color: var(--ink3); margin-top: -6px; }
.key-vals { grid-column: 1; display: grid; gap: 5px; }
/* The link is what a producer acts on, so it is the value, and it is never
 * underlined. */
.key-url { font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); overflow-wrap: anywhere; }
.key-phrase { display: inline-flex; align-items: center; gap: 7px; font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.key-phrase .icon { width: 13px; height: 13px; color: var(--ink3); }
.key-none { font: var(--role-secondary); color: var(--ink3); }
.key-state { grid-column: 1; font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; }
.key .ghost { grid-row: 1 / span 4; grid-column: 2; }

/* -------------------------------------------------------------- escalations */

/* Only what waits, a card each, with everything settled folded under one line
 * at the foot. Section 0 allows a second primary where the report says why:
 * each card is a separate object with its own scalar act, which is the
 * accumulating-versus-scalar distinction the system already draws. */
.jobs { display: grid; gap: 14px; }
.jobs[hidden] { display: none; }
.job { display: grid; gap: 14px; min-width: 0; padding: 18px; background: var(--panel); border-radius: var(--r13); }
.job-head { display: flex; align-items: baseline; gap: 12px; }
.job-head h3 { min-width: 0; font: var(--role-current); font-size: var(--role-row-15); line-height: 1.35; letter-spacing: var(--role-tracking); text-wrap: pretty; }
.job-cell { font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); min-width: 0; letter-spacing: var(--role-tracking); }
.job-cell-sub { margin-left: 10px; font-weight: var(--role-current-weight); color: var(--ink3); }
.job-when { margin-left: auto; flex: none; font: var(--role-secondary); color: var(--ink3); white-space: nowrap; }
.job-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; font: var(--role-secondary); color: var(--ink3); margin-top: -8px; }
.job-meta li { display: inline-flex; align-items: center; gap: 6px; color: var(--ink3); min-width: 0; }
.job-meta li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.job-meta .icon { width: 13px; height: 13px; }
.job-meta b { color: var(--ink); font: var(--role-current); font-size: var(--role-row-13); }
.job-said { display: grid; gap: 8px; }
.job-said .verbatim { font: var(--role-body); line-height: 1.6; color: var(--ink); text-wrap: pretty; }
.job-stake { font: var(--role-secondary); line-height: 1.5; color: var(--ink3); text-wrap: pretty; }
.job-reply { display: grid; gap: 8px; padding: 14px; border-radius: var(--r13); background: var(--surf); }
.job-reply h4 { font: var(--role-section); color: var(--ink); }
.job-reply p { font: var(--role-body); line-height: 1.6; color: var(--ink); text-wrap: pretty; }
/* Two frames, each filling its own column: a picture floating small in the
 * middle of its pane is the fault the media rule names. A viewer pane still
 * contains, touching two edges. */
.job-frames { display: grid; gap: 12px; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; padding: 12px; background: var(--stage); border-radius: var(--r13); }
.job-frame { display: grid; gap: 8px; min-width: 0; align-content: start; }
.job-frame img { display: block; width: 100%; height: auto; max-height: 48vh; object-fit: contain; }
.job-frame figcaption { font: var(--role-secondary); line-height: 1.3; color: var(--ink3); }
.job-frame-none { display: grid; place-items: center; aspect-ratio: 4 / 5; color: var(--ink3); background: var(--surf); border-radius: var(--r9); }
.job-frame-none .icon { width: 15px; height: 15px; }
.job-built { font: var(--role-body); line-height: 1.6; color: var(--ink2); }
.job-acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.job-acts .record, .job-acts .gap, .job-acts .composer { width: 100%; }
.job-acts [hidden] { display: none; }
.job-cuts { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.job-cuts li { display: inline-flex; align-items: center; gap: 6px; font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.job-cuts .icon { width: 12px; height: 12px; color: var(--ink3); }
.job-cut-label { font: var(--role-secondary); color: var(--ink3); }
.job-notes { display: grid; gap: 16px; }
.job-note { display: grid; gap: 8px; }
.job-note h3 { display: flex; align-items: baseline; gap: 10px; font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink); }
.job-note .job-reply { display: flex; gap: 8px; align-items: flex-start; padding: 0; background: none; color: var(--ink); font: var(--role-secondary); line-height: 1.55; }
.job-note .job-reply .icon { width: 13px; height: 13px; margin-top: 3px; color: var(--ink3); }
.job-verdict { display: grid; gap: 6px; }
.job-verdict-why { display: flex; gap: 8px; align-items: flex-start; font: var(--role-secondary); line-height: 1.5; color: var(--ink3); }
.job-verdict-why .icon { width: 13px; height: 13px; margin-top: 2px; }
.job-verdict.is-ok .job-verdict-why .icon { color: var(--ok); }
.job-verdict.is-no .job-verdict-why .icon { color: var(--ink); } /* a verdict of no is a finding, not an ask on you: ink */
.job-claims { display: grid; gap: 4px; padding-left: 21px; }
.job-claims li { display: flex; gap: 8px; align-items: flex-start; font: var(--role-secondary); line-height: 1.5; color: var(--ink3); }
.job-claims .icon { width: 12px; height: 12px; margin-top: 2px; }
.job-claims .is-ok .icon { color: var(--ok); }
.job-claims .is-no .icon { color: var(--ink); } /* the cross is the word; it needs no gold */
.job-composer:has(textarea:placeholder-shown) .composer-acts .tonal {
  background: var(--surf2); color: var(--ink2); opacity: 1; pointer-events: auto;
}
.job-composer textarea { min-height: 56px; }
.job-link { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.job-link .icon { width: 15px; height: 15px; }
.jobs-page .jobs { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; gap: 20px; }
.jobs-page { max-width: 1168px; }

/* --------------------------------------------------------------------- item */

/* One sentence for the layout: what they said, what changed and the pictures
 * read down the column, and the decision stands beside them. */
.item { display: grid; gap: 28px; grid-template-columns: minmax(0, 768px) 360px; align-items: start; }
.told { display: grid; gap: 24px; min-width: 0; align-content: start; }
.side { display: grid; gap: 12px; align-content: start; min-width: 0; }
.said { display: grid; gap: 8px; }
.verbatim { color: var(--ink); font: var(--role-body); line-height: 1.6; white-space: pre-wrap; }
.changed { color: var(--ink2); font: var(--role-body); line-height: 1.6; }
.gap { color: var(--ink3); font: var(--role-secondary); line-height: 1.5; }

/* The work, in the media well. No frame drawn on it: the picture stops where
 * it stops and the well is what is left. */
.stage { display: grid; gap: 20px; min-width: 0; background: var(--stage); border-radius: var(--r13); padding: 16px; }
.shot { display: grid; gap: 8px; min-width: 0; }
.shot img { display: block; width: 100%; height: auto; max-height: 62vh; object-fit: contain; }

/* David, 12 September 2026: "We killed this blurred background gradient
 * long ago. I am angry that I keep seeing it." Use the client room's fixed
 * tonal pools. The media image never paints the background. */
.pane { position: relative; display: block; min-width: 0; isolation: isolate; }
.pane > img { position: relative; z-index: 1; }
.stage-ground { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.stage-ground img, .cell-frame > .stage-ground img { display: none; }
.stage-ground::before {
  content: ""; position: absolute; inset: -5%;
  background:
    radial-gradient(60% 75% at 14% 8%, var(--lift2) 0%, transparent 66%),
    radial-gradient(95% 95% at 58% 60%, var(--lift) 0%, transparent 74%);
  filter: blur(52px);
}
.shot figcaption { font: var(--role-secondary); color: var(--ink3); }

/* The decision surface: one column, centred, the width of a form. On a phone
 * it is the whole width and reads top to bottom without a scroll for a short
 * note: picture, their words, what is at stake, the call. */
.item.is-decision { grid-template-columns: minmax(0, 560px); justify-content: center; gap: 16px; }
.is-decision .told { gap: 16px; }
.is-decision .said h2 { display: flex; align-items: baseline; gap: 10px; }
.said-when { font: var(--role-secondary); color: var(--ink3); }
.stake { color: var(--ink3); font: var(--role-secondary); line-height: 1.5; }

/* The cell the note is about, at its own ratio, the drawing over it in the
 * room's iris. No frame on the picture: it stops where it stops. */
.cell-stage { padding: 12px; }
.cell { justify-items: center; }
.cell-frame {
  isolation: isolate;
  position: relative; max-width: 100%;
  aspect-ratio: var(--arw, 16) / var(--arh, 9);
  width: min(100%, calc(40vh * var(--arw, 16) / var(--arh, 9)));
}
.cell-frame img { display: block; width: 100%; height: 100%; object-fit: contain; }
.anno { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.anno path, .anno line, .anno rect {
  stroke: var(--acc2); stroke-width: 3; fill: none; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.anno .anno-head { fill: var(--acc2); stroke: var(--acc2); stroke-width: 1; stroke-linejoin: round; }

/* Send, and what sending says, as one control. The verb is the button's
 * weight; the label sits one weight down beside it. */
.send { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-width: 0; text-align: left; }
.send-verb { flex: none; }
.send-label { font-weight: var(--role-current-weight); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cream .send-label { opacity: .78; }
.options { display: grid; gap: 8px; }
.options[hidden] { display: none; }
.options .edit { justify-self: start; gap: 8px; }
.options .edit .icon { width: 13px; height: 13px; }
.is-decision .composer textarea { min-height: 132px; }

/* ----------------------------------------------------------------- decision */

.decide-box { display: grid; gap: 12px; }
.record[hidden] { display: none; }
/* Once the act is recorded the control leaves and the record stands in its
 * place. A disabled Approve would be a value wearing control clothing. */
.record { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; font: var(--role-secondary); color: var(--ink3); }
.record b { font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); }
.record.is-ok b { color: var(--ok); }
.record.is-ok { color: var(--ink3); }

/* A composer is a surface, not a bordered box: focus is a glow. It mounts only
 * once the act it belongs to has been asked for, and it takes its own Cancel
 * rather than a close cross. */
.composer {
  background: var(--surf); border-radius: var(--r13); padding: 16px; display: grid; gap: 8px;
  transition: box-shadow var(--slow) var(--ease), background var(--slow) var(--ease);
}
.composer[hidden] { display: none; }
.composer:focus-within { box-shadow: var(--ring-quiet); background: var(--lift); }
.composer label { font: var(--role-section); font-size: var(--role-row-13); line-height: 1; color: var(--ink3); }
.composer textarea {
  width: 100%; background: none; border: 0; resize: vertical; min-height: 76px;
  font: var(--role-body);
  line-height: 1.6; color: var(--ink); caret-color: var(--acc2);
}
.composer textarea:focus, .composer textarea:focus-visible { outline: 0; box-shadow: none; }
.composer-acts { display: flex; align-items: center; gap: 8px; }
.composer-acts .tonal { margin-left: auto; }
.composer-acts > .cream { margin-left: auto; }
/* Prevent and refuse: the commit is inert until the note has words, so an empty
 * send cannot happen and no warning has to be written under the box. */
.composer:has(textarea:placeholder-shown) .composer-acts .tonal {
  background: var(--surf2); color: var(--ink3); opacity: .55; pointer-events: none;
}

/* --------------------------------------------------------------------- walk */

/* The one control that never moves, pinned to the foot of the window at every
 * width. Opaque, because a translucent bar reads as floating over the work,
 * which is exactly what it was doing on a phone. Every page reserves its height
 * plus a gutter, so nothing is ever underneath it at rest. */
.walkbar {
  position: fixed; inset: auto 0 0 0; z-index: 80;
  background: var(--panel);
}
.walkbar-inner {
  display: flex; align-items: center; gap: 12px; min-height: var(--walk);
  max-width: 1168px; margin: 0 auto;
  padding: 8px var(--gutter) calc(8px + env(safe-area-inset-bottom));
}
.walk-end { font: var(--role-secondary); color: var(--ink3); }
.walk-end[hidden], .walk-prev[hidden] { display: none; }
/* No gap between the word and where it goes: the colon belongs to the label,
 * not to the layout. The arrow keeps its own space. */
.walk-next {
  margin-left: auto; min-width: 0; display: inline-flex; align-items: center; gap: 0;
  justify-content: center; white-space: nowrap; overflow: hidden;
}
.walk-next .walk-to { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.walk-next .walk-to::before { content: ": "; }
.walk-next .icon { width: 15px; height: 15px; margin-left: 8px; }

/* --------------------------------------------------------------------- gate */

.gate { min-height: 100dvh; }

/* The door's rules are not here. They are in door.css, imported at the top of
 * this file, which is the one part every Caliba surface wears: this room, the
 * producer room and the Studio. This block held a byte-identical copy of
 * app.css's until 16 September 2026, which is the drift R41 exists to stop.
 * Change review-portal/docs/design/parts/door.html, run its emitter, and
 * review-portal/tests/door-parity.mjs holds the three copies together. */

/* A room link, on the wrong building: one line and the way in. */
.refusal { min-height: 100dvh; display: grid; place-items: center; padding: 24px; }
.refusal div { display: grid; gap: 12px; justify-items: start; max-width: 34ch; }
.refusal p { font: var(--role-secondary); line-height: 1.5; color: var(--ink2); }

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

/* ------------------------------------------------------------------- narrow */

@media (max-width: 1000px) {
  .item { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .jobs-page .jobs { grid-template-columns: minmax(0, 1fr); }
  .person-cols { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .rooms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .person-row { grid-template-columns: 36px minmax(120px, 180px) minmax(0, 1fr) auto; gap: 12px; }
}

/* The phone is drawn, not squeezed. The four destinations move out of the
 * topbar into one bar across the foot, where a thumb reaches and where all
 * four fit without being cut; the topbar goes back to 56px with the wordmark
 * and the avatar on it; the dock collapses to one control that names the room
 * it is showing; and every panel becomes a sheet. */
@media (max-width: 760px) {
  :root { --gutter: 16px; }
  .bar { grid-template-columns: 1fr auto; padding: 0 16px; }
  .bar .sep, .bar .me-name { display: none; }
  /* The separator carried the space between the wordmark and the scope, so
   * when it goes the space has to come from somewhere. */
  .bar-l { gap: 10px; }
  .nav {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60; height: 60px;
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 0;
    background: var(--bg); border-top: 1px solid var(--rule);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .nav-item { height: 60px; justify-content: center; }
  /* R7: the current destination is ink and 600 on the bottom bar as on the
   * topbar, and no underline says "on" here either. */
  .nav-item[aria-current="page"] { font-weight: var(--role-current-weight); }
  /* The bottom bar's own height, added under everything rather than taken out
   * of the page's walk clearance: the page keeps the clearance it reserves at
   * every width, and the bar sits under it. */
  body { padding-bottom: calc(60px + env(safe-area-inset-bottom)); }
  .walkbar { bottom: calc(60px + env(safe-area-inset-bottom)); }
  .r2-in { padding: 0 16px; }
  /* One dock on a phone: the desktop's four collapse into the one that names
   * what you are looking at. */
  .r2:first-of-type { display: none; }
  .r2 + .r2 { display: block; }
  /* A person's row on a phone: the disc and the name on one line, the facts
   * under them, wrapping where the words are longer than the screen. */
  .people { gap: 4px; }
  .rooms { grid-template-columns: minmax(0, 1fr); }
  .person-row { grid-template-columns: 36px minmax(0, 1fr); row-gap: 4px; padding: 10px; }
  .person-row .avatar { grid-row: span 2; }
  .prow-facts, .prow-end { grid-column: 2; }
  .prow-end { justify-self: start; }
  .prow-menu { opacity: 1; }
  .prow-line { white-space: normal; overflow-wrap: anywhere; }
  .room-bar .progress-track, .person-bar .progress-track { width: 100%; }
  .room-head { flex-wrap: wrap; gap: 4px 12px; }
  .room-wait { margin-left: 0; width: 100%; }
  .person-head { flex-wrap: wrap; }
  .person-att { margin: 12px 0 0; width: 100%; justify-items: start; text-align: left; }
  .job-frames { grid-template-columns: minmax(0, 1fr); }
  .job-acts { flex-direction: column; align-items: stretch; }
  .job-acts .cream, .job-acts .tonal, .job-acts .violet { width: 100%; }
  .chg-row, .cell-row { grid-template-columns: 48px minmax(0, 1fr); }
  .chg-when { grid-column: 2; padding-top: 2px; }
  .cell-row .state { grid-column: 2; }
  .row { padding: 12px 10px; }
  .job { padding: 14px; }
  .cell-frame { width: min(100%, calc(30vh * var(--arw, 16) / var(--arh, 9))); }
  .is-decision .composer textarea { min-height: 112px; }
  .stage { padding: 12px; border-radius: var(--r13); }
  .shot img { max-height: none; }
  /* The two things a decision is made of go full width rather than two half
   * buttons a thumb has to pick between. */
  .cream, .tonal { width: 100%; }
  .composer-acts .tonal, .composer-acts .cream { width: auto; }
  .panel, .modal {
    left: 0; top: auto; bottom: 0; transform: none; width: 100%; max-height: 92%;
    border-radius: var(--r13) var(--r13) 0 0; border-bottom: 0;
  }
  .modal { top: 0; bottom: 0; max-height: none; border-radius: 0; } /* R43: named recipe, not a box: square: the modal fills the phone */
  .modal-body { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .modal-foot { display: block; }
  .modal-foot .violet { width: 100%; }
  .panel-top, .modal-top { padding-left: 16px; }
  .panel-body, .modal-body, .modal-foot { padding-left: 16px; padding-right: 16px; }
  .mem-row {
    display: grid; grid-template-columns: 28px minmax(0, 1fr);
    align-items: center; column-gap: 10px; row-gap: 9px; padding: 12px 0;
  }
  .mem-access { grid-column: 2; justify-self: start; max-width: none; }
  .mem-cadence { grid-column: 2; justify-self: start; max-width: none; }
  .pop { left: 16px; right: 16px; max-width: none; width: auto; }
  .pop-account, .pop-person, .pop-access { left: auto; right: 16px; }
  .ops-people .bar { height: 52px; padding: 0 12px; }
  /* 100dvh - 140: 60 of bar and margin above, the nav's 56 and the window's
   * 8 below, and the 8 gutter between panel and nav, so a short room's panel
   * ends at 772 rather than touching the nav (same rule as the desktop's). */
  .ops-people .page.people-page { min-height: calc(100dvh - 140px); margin: 8px; padding: 16px; }
  .ops-people .people { grid-template-columns: minmax(0, 1fr); gap: 12px; margin-top: 18px; }
  .ops-people .person-row {
    display: grid; grid-template-columns: 36px minmax(0, 1fr) 24px; grid-template-rows: auto auto 1fr auto;
    column-gap: 12px; row-gap: 0; min-height: 224px; padding: 16px;
  }
  .ops-people .person-row .avatar { grid-row: auto; }
  .ops-people .person-row .prow-facts, .ops-people .person-row .prow-end { grid-column: 1 / -1; }
  .ops-people .person-row .prow-end { justify-self: start; }
  .ops-people .room-bar .progress-track { width: 180px; }
  .ops-people .people-producers-heading { margin-top: 28px; }
  .ops-people .people-producers .mem-row { display: grid; grid-template-columns: 36px minmax(0, 1fr); column-gap: 12px; padding: 0 8px; }
  .ops-people .people-producers .mem-cadence { grid-column: 2; justify-self: start; }
  .ops-people .pop-account { position: fixed; top: 68px; left: 8px; right: 8px; width: auto; max-width: none; padding: 10px 12px 12px; }
  .ops-people .pop-account .pop-who { height: 38px; }
  .ops-people .cadence-row, .ops-people .pop-account .pop-item { height: 48px; }
  .ops-people .cadence-list { position: fixed; left: 8px; right: 8px; top: 344px; width: auto; max-height: calc(100dvh - 412px); }
  .ops-people .cadence-list-scroll { max-height: inherit; }
  .ops-people .nav { left: 8px; right: 8px; bottom: 8px; height: 56px; border: 0; border-radius: var(--r13); background: var(--panel); padding: 0 10px; }
  .ops-people .nav-item { height: 56px; }
}

/* A producer mints a sign-in code for one named address, on the key it opens. */
.key-issue { display: flex; align-items: center; gap: 6px; }
.key-issue select { min-width: 0; height: 34px; padding: 0 8px; border-radius: var(--r6); background: var(--lift); box-shadow: var(--edge); color: var(--ink2); font: var(--role-current); font-size: var(--role-row-13); line-height: 1; }
.key-issue select:focus-visible { outline: 0; box-shadow: inset 0 0 0 1px var(--acc), 0 0 0 3px var(--acc-bg); }
.key-note { display: flex; align-items: center; gap: 10px; color: var(--ink2); font: var(--role-current); font-size: var(--role-row-13); }
.key-note code { color: var(--ink); font: var(--role-current); font-size: var(--role-row-24); line-height: 1; font-variant-numeric: tabular-nums; }
.key-note.is-error { color: var(--danger); } /* an error is a refusal, not a state: rose, never gold */

/* ---------------------------------------------------------------------- desk
 *
 * Built to docs/design/producer-room/ (drawn 14 September 2026, approved in
 * docs/design/REGISTER.json): the desk as type in space, one column at the
 * room's own measure, two groups under disclosures, two lines a row and the
 * execution, who and when on the right in twelve-point.
 *
 * R65, David 13 September: "these row designs, with bunched up rows with the
 * same background that looks like a hover, is very wrong." No row carries a
 * fill at rest; the rows are held apart by their spacing and the ink of their
 * words, and the one fill on this page means the pointer is over a row. The
 * was-and-now pair is type in space too: no band under it, no button beside
 * it, the old line struck quietly beside the new one.
 *
 * R29: the row is the act and opens the thread, so no control sits on it; a
 * reply row's one quiet eye glyph is the row's own title, not a control.
 */
.desk-page { max-width: 768px; }
/* A room the store would not answer for is said out loud rather than read as
 * an empty desk: showing nothing when something waits is the one failure this
 * page exists to prevent. */
.desk-stale { margin-bottom: 20px; font: var(--role-secondary); line-height: 1.45; color: var(--ink3); }

.desk-group { margin-top: 26px; }
.desk-group:first-child { margin-top: 0; }
/* The group's rows stand in space (R65; the walk of 15 September 2026, Desk
 * group background): no well, no panel behind them, the heading above and the
 * spacing between them doing all the separating. */
.desk-rows { display: grid; gap: 2px; }
.desk-rows[hidden] { display: none; }

.desk-row { grid-template-columns: minmax(0, 1fr) auto auto; align-items: start; gap: 18px; padding: 14px 14px; }
.desk-body { min-width: 0; display: grid; gap: 4px; }
.desk-l1 { font: var(--role-body); line-height: 1.5; color: var(--ink); text-wrap: pretty; }
.desk-l1 q { quotes: "\201C" "\201D"; }
.desk-l1 b { font-weight: var(--role-current-weight); }
.desk-l2 { font: var(--role-secondary); line-height: 1.5; color: var(--ink3); text-wrap: pretty; }
.desk-l2 b { font-weight: var(--role-current-weight); color: var(--ink2); }
.desk-l2 s { color: var(--ink4); text-decoration-color: var(--rule2); }
.desk-l2 b + s { margin-left: 10px; }
.desk-side { display: grid; gap: 4px; justify-items: end; text-align: right; padding-top: 2px; font: var(--role-secondary); font-size: var(--role-row-12); color: var(--ink3); white-space: nowrap; }
.desk-side span + span { color: var(--ink4); }
/* The act column holds one width on every row, filled or empty (the desk's
 * one-width law, David 19 September 2026: "Two different column widths makes
 * this look broken."): the eye's 16 is held by an empty column too, so the
 * meta column's right edge and the words column's right edge keep one x
 * down the whole list. */
.desk-row .row-glyph { color: var(--ink4); padding-top: 3px; width: 16px; }
.desk-row .row-glyph svg { width: 16px; height: 16px; }
a.desk-row:hover .row-glyph { color: var(--ink); }

/* A row the room turned away (CAL-713) says its one word under the who and
 * when, in the fourth ink: it is the record of a leave, not a thing to act
 * on, so the act column stands empty and keeps its width like a wording
 * row's does. */
.desk-left-row .desk-l1, .desk-left-row .desk-l2 { color: var(--ink3); }

/* R17 and R34 on an empty desk: one sentence, no illustration, no heading,
 * no count of zero, and no empty groups each saying they are empty. */
.desk-empty { margin-top: 20px; font: var(--role-body); line-height: 1.6; color: var(--ink3); }

/* The phone: the words and their line first, then the execution, who and when
 * on a line of their own. Nothing wraps under anything. */
@media (max-width: 719px) {
  .desk-row { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .desk-side { justify-items: start; text-align: left; grid-auto-flow: column; gap: 10px; }
}

/* ============================================================= the review
 * R81, 14 September 2026: "A producer must review each change and release to
 * client, looking at the note and editing it if necessary." One change, one
 * review, one press. The note as written, the cut parked at the frame the
 * note addresses, the reply in the producer's own hands, and the frames the
 * claim is read from beside it. The decision lives in the room's thread
 * (R29), so this is that thread, as the producer sees it.
 */

/* The stage and the thread are two windows, 8 apart, never a hairline
 * between them (CAL-1537). */
.rev { grid-row: 2 / -1; display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 8px; padding: 8px; min-height: 0; overflow: hidden; }
.rev-stage { position: relative; background: var(--stage); display: grid; place-items: center; min-width: 0; border-radius: var(--r13); overflow: hidden; }
.rev-stage .shot { width: 100%; height: 100%; background-size: cover; background-position: center; }
.rev-scrub { position: absolute; left: 0; right: 0; bottom: 0; display: grid; gap: 8px; padding: 14px 16px 16px;
  background: linear-gradient(to top, var(--scrim), transparent); }
.rev-track { position: relative; height: 3px; border-radius: 999px; background: var(--track); } /* R43: named recipe, not a box: pill */
.rev-played { position: absolute; inset: 0 auto 0 0; width: 47%; border-radius: 999px; background: var(--ink); }
.rev-pin { position: absolute; top: -4px; left: 47%; width: 2px; height: 11px; border-radius: 999px; background: var(--acc2); } /* an open thing on the scrub is the accent, never gold. R43: named recipe: a 2px pin is a pill of its own */
.rev-times { display: flex; justify-content: space-between; font: var(--role-current); font-size: var(--role-row-12); line-height: 1; color: var(--ink2); }
.rev-at { color: var(--ink); } /* a moment in time is a value in ink, not an ask */

.rev-side { min-width: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; background: var(--panel); border-radius: var(--r13); overflow: hidden; }
.rev-scroll { overflow: auto; padding: 20px; display: grid; gap: 18px; align-content: start; }
.rev-items { display: flex; flex-wrap: wrap; gap: 4px; padding-bottom: 2px; }
.rev-items a { flex: 0 0 auto; max-width: 100%; padding: 7px 9px; border-radius: var(--r6); color: var(--ink3); font: var(--role-secondary); font-size: var(--role-row-12); line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rev-items a:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.rev-items a:hover { color: var(--ink2); background: var(--surf); }
.rev-items a[aria-current="page"] { color: var(--ink); background: var(--surf2); }
.rev-note { display: grid; gap: 8px; }
.rev-who { display: flex; align-items: center; gap: 8px; font: var(--role-current); font-size: var(--role-row-13); line-height: 1.3; color: var(--ink2); }
.rev-who .avatar { width: 24px; height: 24px; font-size: var(--role-row-12); }
.rev-who time { color: var(--ink3); }
.rev-note .verbatim { font: var(--role-body); font-size: var(--role-row-15); line-height: 1.6; color: var(--ink); }
.rev-cell { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 10px; font: var(--role-secondary); line-height: 1.3; color: var(--ink3); }
.rev-progress { font: var(--role-secondary); color: var(--ink3); }

.rev-sec > h3 { font: var(--role-secondary); font-size: var(--role-row-12); line-height: 1.5; color: var(--ink3); margin-bottom: 8px; }
.rev-field {
  display: grid; gap: 10px; padding: 12px; border-radius: var(--r13);
  background: var(--surf); box-shadow: inset 0 0 0 1px var(--rule);
}
.rev-field.editing { background: var(--surf2); box-shadow: inset 0 0 0 1px var(--acc); }
.rev-text { font: var(--role-body); line-height: 1.6; color: var(--ink); text-wrap: pretty; }
.rev-caret { display: inline-block; width: 1.5px; height: 16px; vertical-align: -3px; margin-left: 1px; background: var(--acc2); }
.rev-field-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; font: var(--role-secondary); font-size: var(--role-row-12); color: var(--ink4); }
.rev-drafted { color: var(--ink4); }

.rev-claims { display: grid; gap: 10px; }
.rev-claim { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 12px; align-items: center; }
.rev-frame { width: 96px; height: 54px; border-radius: var(--r6); background: var(--stage) center/cover no-repeat; }
.rev-claim p { font: var(--role-secondary); line-height: 1.5; color: var(--ink2); text-wrap: pretty; }
.rev-claim b { display: block; font: var(--role-secondary); font-size: var(--role-row-12); line-height: 1.5; color: var(--ink4); }

.rev-locked {
  display: grid; gap: 8px; padding: 14px; border-radius: var(--r13);
  background: var(--lift); box-shadow: inset 0 0 0 1px var(--rule);
}
.rev-locked h3 { display: flex; align-items: center; gap: 8px; font: var(--role-current); font-size: var(--role-row-13); color: var(--ink); } /* a finding, not an ask on you: ink */
.rev-locked h3 svg { width: 15px; height: 15px; }
.rev-locked p { font: var(--role-secondary); line-height: 1.55; color: var(--ink2); text-wrap: pretty; }

.rev-acts { display: flex; align-items: center; gap: 10px; padding: 16px 20px; border-top: 1px solid var(--rule); }
.rev-acts .cream { flex: 1; }
.rev-acts .cream[aria-disabled="true"] { background: var(--surf2); color: var(--ink4); }
.rev-sent { display: flex; align-items: center; gap: 8px; font: var(--role-current); font-size: var(--role-row-13); color: var(--ok); }
.rev-sent svg { width: 16px; height: 16px; }

.is-phone .rev { grid-template-columns: minmax(0, 1fr); grid-template-rows: 240px minmax(0, 1fr); }
.is-phone .rev-scroll { padding: 16px; }
.is-phone .rev-acts { padding: 12px 16px; }
.is-phone .rev-page .rev { min-height: 0; }

@media (max-width: 719px) {
  .rev { grid-template-columns: minmax(0, 1fr); grid-template-rows: 240px auto; }
  .rev-scroll { padding: 16px; min-width: 0; }
  .rev-acts { padding: 12px 16px; }
  .rev-text { width: 100%; min-width: 0; box-sizing: border-box; }
}

/* The review plays the selected version without cropping its frame. */
.rev-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.rev-stage:has(.rev-media) .rev-scrub { top: 0; bottom: auto; pointer-events: none; background: none; }
.rev-media-error { position: relative; padding: 20px; color: var(--ink2); }

/* ---------------------------------------------------------- languages page
 *
 * docs/design/languages-link, drawn 13 September 2026: one row per language
 * link, the four facts a producer asks for, the address in a pill that IS
 * the copy, and no lock control anywhere. Rows separate by the ramp (R10),
 * stand 10 apart (14 on the phone), and the only fill in the list at rest is
 * the pointer's (R6, R65). The panel is the Modal recipe: 880 at r13 on
 * --panel over --scrim, two equal columns, one iris primary at the footer's
 * right, which is legal there and only there. */
.ops-languages .page.languages-page {
  width: auto; max-width: none; min-height: calc(100dvh - 72px);
  margin: 8px; padding: 8px 0 0; background: var(--panel); border-radius: var(--r13);
}
.lg-section + .lg-section { margin-top: 28px; }
.lg-section .disc { margin: 0 24px 10px; }

/* The band under the bar holds the page's one act, at its right (the
 * executions page's own row two). Cream: the page's primary. */
.lg-band { display: flex; align-items: center; min-height: 56px; padding: 0 24px; }
.lg-issue-page {
  margin-left: auto; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 38px; padding: 0 16px; border-radius: var(--r9); background: var(--ink);
  color: var(--panel); font: var(--role-current); font-size: var(--role-row-15); line-height: 1;
}
.lg-issue-page:hover { background: var(--cream-hover); }
.lg-issue-page .icon { width: 17px; height: 17px; color: var(--panel); }

.lg-list { display: flex; flex-direction: column; gap: 10px; padding: 0 24px 24px; list-style: none; }
.lg-row {
  position: relative; display: flex; align-items: center; gap: 20px; height: 56px;
  padding: 0 12px 0 16px; border-radius: var(--r9); flex: none; width: 100%;
}
.lg-row:hover { background: var(--hov); }
.lg-name {
  flex: none; width: 180px; min-width: 0; font: var(--role-current); font-size: var(--role-row-15); line-height: 1; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lg-who {
  flex: none; width: 240px; min-width: 0; display: flex; align-items: center; gap: 10px;
  font: var(--role-current);
  line-height: 1; color: var(--ink2); white-space: nowrap; overflow: hidden;
}
.lg-who-one { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.lg-who .avatar { width: 26px; height: 26px; font: var(--role-current); font-size: var(--role-row-12); line-height: 1; }
.lg-who-none { color: var(--ink3); }
.lg-tier { flex: none; width: 130px; display: flex; align-items: center; gap: 8px; font: var(--role-current); line-height: 1; color: var(--ink3); }
.lg-tier .icon { width: 16px; height: 16px; color: var(--glyph); }
.lg-addr { flex: 1; min-width: 0; display: flex; align-items: center; }
.lg-pill {
  display: inline-flex; align-items: center; gap: 8px; height: 30px; padding: 0 11px;
  border-radius: var(--r6); background: var(--hov); color: var(--ink2);
  font: var(--role-current);
  font-size: var(--role-row-13);
  line-height: 1; max-width: 100%; white-space: nowrap; overflow: hidden;
}
button.lg-pill:hover { background: var(--hov2); color: var(--ink); }
.lg-pill .icon { width: 15px; height: 15px; color: var(--glyph); opacity: 0; }
.lg-row:hover .lg-pill .icon { opacity: 1; }
.lg-row.over .lg-pill { color: var(--ink4); }
.lg-state {
  flex: none; width: 190px; display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  font: var(--role-current);
  line-height: 1; color: var(--ink3);
}
.lg-state .icon { width: 15px; height: 15px; color: var(--glyph); }
.lg-state.is-live, .lg-state.is-live .icon { color: var(--ok); }
.lg-state.is-over { color: var(--ink4); }
.lg-acts {
  flex: none; width: 34px; height: 34px; border-radius: var(--r9); display: grid;
  place-items: center; color: var(--glyph); opacity: 0;
}
.lg-row:hover .lg-acts, .lg-acts:focus-visible { opacity: 1; }
.lg-acts:hover { background: var(--hov2); color: var(--ink); }
.lg-acts .icon { width: 18px; height: 18px; }
.lg-row.over .lg-name { color: var(--ink3); font-weight: var(--role-current-weight); }

/* The row's menu: 240 and never wider, no title, rows of 40 with a solid
 * glyph, the destructive act last behind the ramp's one hairline (R40). */
.lg-menu {
  position: absolute; top: 42px; right: 12px; left: auto; width: 240px; max-width: none;
  padding: 6px; display: flex; flex-direction: column;
}
.lg-mrow {
  display: flex; align-items: center; gap: 12px; height: 40px; padding: 0 10px;
  border-radius: var(--r6); font: var(--role-current); line-height: 1; color: var(--ink2); width: 100%;
}
.lg-mrow .icon { width: 17px; height: 17px; color: var(--glyph); }
.lg-mrow:hover, .lg-mrow:hover .icon { background: var(--hov); color: var(--ink); }
.lg-mrow.is-gone, .lg-mrow.is-gone .icon { color: var(--danger); }
.lg-mrow.is-gone:hover, .lg-mrow.is-gone:hover .icon { background: var(--state-danger-bg); color: var(--danger); }
.lg-mdiv { height: 1px; background: var(--rule); margin: 6px 10px; }

/* The panel: the Modal recipe whole. */
.lg-modal {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 71;
  width: min(880px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); overflow: auto;
  background: var(--panel); border-radius: var(--r13); box-shadow: var(--shadow-menu);
  display: flex; flex-direction: column;
}
.lg-modal[hidden] { display: none; }
/* The two faces trade places, so the one that is hidden has to stay hidden:
 * an explicit display on the class would otherwise paint over the other. */
.lg-body[hidden], .lg-foot[hidden], .lg-made[hidden] { display: none; }
.lg-top { display: flex; align-items: center; gap: 12px; height: 60px; padding: 0 20px 0 28px; flex: none; }
.lg-title { flex: 1; min-width: 0; margin: 0; font: var(--role-current); font-size: var(--role-row-16); line-height: 1; letter-spacing: var(--role-tracking); color: var(--ink); }
.lg-close { width: 34px; height: 34px; border-radius: var(--r9); display: grid; place-items: center; color: var(--glyph); }
.lg-close:hover { background: var(--hov); color: var(--ink); }
.lg-close .icon { width: 17px; height: 17px; }
.lg-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; padding: 4px 28px 8px; }
.lg-col { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.lg-key { font: var(--role-secondary); line-height: 1; color: var(--ink3); }
.lg-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 9px; }
.lg-grid-two { grid-template-columns: 1fr 1fr; }
.lg-card {
  display: flex; align-items: center; gap: 10px; height: 46px; padding: 0 14px;
  border-radius: var(--r13); background: var(--lift); color: var(--ink2);
  font: var(--role-current);
  font-size: var(--role-row-15);
  line-height: 1; width: 100%; white-space: nowrap; overflow: hidden;
}
.lg-card .icon { width: 17px; height: 17px; color: var(--glyph); }
.lg-card:hover { background: var(--lift2); }
/* R6 and R65: the chosen card is one neutral step up the ramp and never an
 * accent fill or ring. */
.lg-card[data-on] { background: var(--surf2); color: var(--ink); }
.lg-card[data-on] .icon { color: var(--ink2); }
.lg-value { display: inline-flex; align-items: center; height: 46px; font: var(--role-current); font-size: var(--role-row-15); line-height: 1; color: var(--ink); }
.lg-field {
  display: block; width: 100%; background: var(--hov); border: 0; border-radius: var(--r9);
  padding: 11px 13px 12px; font: var(--role-body); font-size: var(--role-row-15); line-height: 1.3; color: var(--ink); margin-top: 9px;
}
.lg-field:hover { background: var(--hov2); }
.lg-field:focus-visible { outline: 0; box-shadow: var(--ring); }
.lg-field::placeholder { color: var(--ink3); }
.lg-line { font: var(--role-body); font-size: var(--role-row-15); line-height: 1.5; color: var(--ink3); }
.lg-line b { font-weight: var(--role-current-weight); color: var(--ink); }
.lg-wells { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
/* A well covers: the picture is cropped to the slot and centred, never a bar
 * of empty well, and there is one well size for the whole grid. */
.lg-well { display: block; width: 100%; aspect-ratio: 4 / 5; border-radius: var(--r9); background-size: cover; background-position: center; background-color: var(--lift); }
.lg-foot { display: flex; align-items: center; gap: 14px; height: 76px; padding: 0 28px; flex: none; }
.lg-error { margin: 0; margin-right: auto; font: var(--role-current); font-size: var(--role-row-13); color: var(--danger); }
.lg-primary {
  margin-left: auto; display: inline-flex; align-items: center; justify-content: center;
  height: 40px; padding: 0 20px; border-radius: var(--r9); background: var(--acc);
  color: var(--white); font: var(--role-current); font-size: var(--role-row-15); line-height: 1;
}
.lg-primary:hover { background: var(--acc-hover); }
/* The link, once: the act is over, so the footer is gone with it, and there
 * is ONE thing to hand over (R58). */
.lg-made { display: flex; flex-direction: column; gap: 10px; padding: 4px 28px 28px; }
.lg-addr-made {
  display: flex; align-items: center; gap: 10px; height: 48px; padding: 0 8px 0 16px;
  border-radius: var(--r9); background: var(--hov); font: var(--role-current); font-size: var(--role-row-15); line-height: 1; color: var(--ink);
}
.lg-addr-made span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lg-copy { flex: none; width: 34px; height: 34px; border-radius: var(--r9); display: grid; place-items: center; color: var(--glyph); }
.lg-copy:hover { background: var(--hov2); color: var(--ink); }
.lg-copy .icon { width: 17px; height: 17px; }
.lg-rec { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
.lg-one {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 32px;
  font: var(--role-current);
  line-height: 1; color: var(--ink3);
}
.lg-one b { font-weight: var(--role-current-weight); color: var(--ink2); }

/* The phone: the row becomes two lines, the address goes (a phone is where a
 * producer checks who has what, not where they hand a link over), and the
 * acts glyph stands rather than waiting for a pointer. The panel is a
 * full-height sheet with the primary across the foot. */
@media (max-width: 760px) {
  .lg-band { min-height: 44px; padding: 0 12px; }
  .lg-issue-page { height: 44px; padding: 0 14px; }
  .lg-list { padding: 0 8px 16px; gap: 14px; }
  .lg-row { height: 72px; padding: 0 6px 0 10px; flex-wrap: wrap; align-content: center; gap: 8px; row-gap: 8px; }
  .lg-name { width: auto; flex: 1; order: 0; min-width: 0; }
  .lg-state { width: auto; flex: none; order: 0; }
  .lg-row::after { content: ""; order: 1; flex-basis: 100%; height: 0; }
  .lg-who { width: auto; flex: 1; order: 3; }
  .lg-tier { width: auto; order: 4; flex: none; }
  .lg-addr { display: none; }
  .lg-acts { opacity: 1; order: 5; margin-left: auto; }
  .lg-menu { top: auto; bottom: 40px; right: 6px; }
  .lg-modal {
    left: 0; right: 0; top: auto; bottom: 0; transform: none; width: 100%;
    max-height: calc(100dvh - 56px); border-radius: var(--r13) var(--r13) 0 0;
  }
  .lg-body { grid-template-columns: minmax(0, 1fr); padding: 4px 16px 8px; gap: 18px; }
  .lg-top { padding: 0 10px 0 16px; }
  .lg-foot { padding: 0 16px; height: 84px; }
  .lg-primary { width: 100%; height: 50px; margin: 0; }
  .lg-made { padding: 4px 16px 24px; }
}

.desk-row .row-glyph { position: relative; }
.desk-row .row-glyph .pop { top: 28px; right: 0; left: auto; }
.desk-row .row-glyph .ghost { padding: 0; }
@media (max-width: 719px) {
  .desk-row { position: relative; padding-right: 44px; }
  .desk-row .row-glyph { position: absolute; right: 14px; top: 14px; }
}
