/* Mula application stylesheet.
   Tokens come from design/tokens.css only; this file never declares a :root block.
   Sections 1 to 3 are the ratified site components from design/site/mula.css, copied
   because the application uses them unchanged. Section 4 is the application shell.
   Section 5 holds one marked block per screen; a screen's own rules go in its block
   and nowhere else, so two authors never touch the same lines. */

/* ---------- 1. Base ---------- */
* { box-sizing: border-box; }
body { margin: 0; background: var(--paper); color: var(--ink); font-family: var(--font); font-size: var(--text-17); line-height: 1.55; -webkit-font-smoothing: antialiased; }
h1, h2, h3 { margin: 0; font-family: var(--font-display); font-stretch: 105%; font-weight: 600; letter-spacing: -0.02em; text-wrap: balance; color: var(--ink); }
h1 { font-stretch: 112%; font-weight: 700; font-size: clamp(2rem, 4vw, var(--text-42)); line-height: 1.06; letter-spacing: -0.03em; }
h2 { font-size: clamp(1.5rem, 2.6vw, var(--text-28)); line-height: 1.15; letter-spacing: -0.025em; }
h3 { font-size: var(--text-22); line-height: 1.2; letter-spacing: -0.015em; }
p { margin: 0; color: var(--ink-2); max-width: 60ch; }
a { color: var(--teal); text-decoration: none; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.wrap { max-width: var(--col); margin: 0 auto; padding: 0 var(--space-4); }
@media (max-width: 700px) { .wrap { padding: 0 20px; } }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.accent { color: var(--teal); }
.sub { font-size: var(--text-18); }
.center { text-align: center; }
.band-gray { background: var(--paper-3); }

/* ---------- 2. Buttons, links, fields (from mula.css) ---------- */
.btn { --r: var(--radius-btn); position: relative; isolation: isolate; clip-path: inset(0 round var(--r)); display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1); min-height: 46px; padding: 0 26px; border-radius: var(--r); font-family: var(--font); font-weight: 600; font-size: var(--text-15); border: 1px solid transparent; cursor: pointer; transition: transform var(--dur-press) var(--ease-out), border-color var(--dur-hover) ease, box-shadow var(--dur-hover) ease; }
.btn::before { content: ""; position: absolute; inset: -1px; z-index: -1; background: var(--wash); transform: translateX(-101%); transition: transform 280ms var(--ease-out); }
.btn:active { transform: scale(0.97); }
.btn-primary { background: var(--teal); color: var(--teal-ink); --wash: var(--wash-teal); }
.btn-mint { background: var(--brand-mint); color: var(--mint-ink); --wash: var(--wash-mint); }
.btn-secondary { background: var(--paper-2); color: var(--ink); border-color: var(--line); --wash: var(--wash-white); }
.btn[disabled] { opacity: 0.55; pointer-events: none; }
.btn-wide { width: 100%; }
.link { color: var(--teal); font-weight: 500; font-size: var(--text-15); display: inline-flex; align-items: center; gap: 6px; }
.link::after { content: "→"; transition: transform var(--dur-hover) var(--ease-out); }
.link.back::after { content: none; }
.link.back::before { content: "←"; }
@media (hover: hover) and (pointer: fine) {
  .btn:hover::before { transform: translateX(0); }
  .btn-primary:hover { box-shadow: 0 6px 18px var(--teal-soft); }
  .btn-secondary:hover { border-color: transparent; }
  .link:hover::after { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) { .btn::before { transition: none; } .btn:active { transform: none; } }

.form { display: grid; gap: 22px; }
.field label { display: block; font-size: var(--text-15); font-weight: 500; color: var(--ink); margin-bottom: var(--space-1); }
.field .hint { font-size: var(--text-13); color: var(--ink-2); margin: -4px 0 var(--space-1); }
.field input, .field select, .field textarea { min-height: 46px; width: 100%; padding: 0 14px; border-radius: var(--radius-input); border: 1px solid var(--line); background: var(--paper-2); color: var(--ink); font-family: var(--font); font-size: 1rem; }
.field textarea { padding: 12px 14px; min-height: 92px; resize: vertical; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; border-color: var(--teal); }
.field .err { display: none; color: var(--coral-text); font-size: 0.875rem; margin-top: 6px; }
.field[data-invalid="true"] input { border-color: var(--coral-text); }
.field[data-invalid="true"] .err { display: block; }
.fine { font-size: var(--text-13); color: var(--ink-2); }

/* ---------- 3. Product components (from mula.css) ---------- */
.rows { list-style: none; margin: 0; padding: 0; }
.rows li { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: var(--space-1) 0; border-top: 1px solid var(--line); }
.rows li:first-child { border-top: 0; }
.rows .v { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ok { color: var(--mint); font-weight: 500; }
.no { color: var(--coral-text); font-weight: 500; }
.seg { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; background: var(--paper-3); padding: 4px; border-radius: 10px; }
.seg button { min-height: 46px; border: 0; border-radius: 7px; background: transparent; color: var(--ink-2); font-family: var(--font); font-size: 0.875rem; font-weight: 500; cursor: pointer; padding: 4px 10px; line-height: 1.2; transition: background-color var(--dur-hover) ease, color var(--dur-hover) ease, transform var(--dur-press) var(--ease-out); }
.seg button:active { transform: scale(0.97); }
/* The selected chip's lift is carried verbatim from mula.css: a card shadow is far
   too heavy on a 46px control, and there is no token at this weight. */
.seg button[aria-pressed="true"] { background: var(--paper-2); color: var(--ink); box-shadow: 0 1px 4px rgba(10, 10, 10, 0.10); }
.lines { list-style: none; margin: 6px 0 0; padding: 0; }
.lines li { display: flex; justify-content: space-between; gap: 12px; padding: var(--space-1) 0; border-top: 1px solid var(--line); line-height: 1.3; transition: opacity var(--dur-moment) var(--ease-out), transform var(--dur-moment) var(--ease-out); }
.lines li.pending { opacity: 0; transform: translateY(6px); }
.lines .k small { display: block; color: var(--ink-2); font-size: 0.72rem; margin-top: 1px; }
.lines .v { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.total { display: flex; justify-content: space-between; align-items: baseline; margin-top: 6px; padding-top: 12px; border-top: 2px solid var(--ink); }
.total .k { font-weight: 600; }
.total .v { font-family: var(--font-display); font-stretch: 108%; font-size: var(--text-18); font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.excerpt { font-family: var(--mono); font-size: 0.78rem; line-height: 1.55; background: var(--paper-3); border-radius: var(--radius-input); padding: 12px 14px; color: var(--ink); }
.excerpt .label { font-family: var(--font); font-size: 0.72rem; color: var(--ink-2); margin-bottom: 6px; }
.flag { margin-top: 12px; padding: 10px 12px; border-radius: var(--radius-input); background: var(--tint-peach); font-size: var(--text-13); color: var(--ink); }
.flag b { color: var(--coral-text); }
.checks { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 10px; font-size: var(--text-15); color: var(--ink); }
.checks li { display: flex; gap: 10px; align-items: flex-start; }
.checks svg { width: 18px; height: 18px; flex: none; margin-top: 3px; color: var(--teal); }
.glass { position: relative; isolation: isolate; border: 0; }
.glass::before { content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1; background: var(--sheen); mix-blend-mode: screen; pointer-events: none; }
.glass::after { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: var(--rim); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; }

/* ---------- 4. Application shell ---------- */
/* The header is the site's glass pill, shortened, carrying the production being
   viewed instead of marketing links. Working pages get a footer that says who
   stands behind the paper. */
.appbar { position: sticky; top: 0; z-index: 50; padding: 12px 16px 0; }
.pill { max-width: var(--col); margin: 0 auto; border-radius: var(--radius-pill); overflow: hidden; --rim: var(--rim-light); background: var(--glass-light); box-shadow: var(--glass-shadow-light); -webkit-backdrop-filter: var(--glass-blur-light); backdrop-filter: var(--glass-blur-light); transition: background-color var(--dur-reveal) ease, box-shadow var(--dur-reveal) ease; }
.pill[data-at-top="true"] { background: var(--glass-light-top); box-shadow: none; }
@media (prefers-reduced-transparency: reduce) { .pill { background: var(--paper); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: 0 0 0 1px var(--line); } .glass::before, .glass::after { display: none; } }
.pillrow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); height: 56px; padding: 0 var(--space-2) 0 22px; }
.logo { display: inline-flex; align-items: center; color: var(--ink); }
.logo svg { height: 22px; width: auto; display: block; }
.appnav { display: flex; align-items: center; gap: var(--space-3); font-size: var(--text-15); min-width: 0; }
.appnav .who { color: var(--ink-glass-2); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.appnav a:not(.btn) { color: var(--ink-glass-2); font-weight: 500; }
.appnav .btn { --r: 999px; min-height: 38px; padding: 0 var(--space-2); font-size: var(--text-13); }
/* Notifications live in the header, which is where the plan says a producer
   comes back to them. It is a dot rather than a number: the sidebar already
   carries a 4 on Tasks, and two different fours in one bar is a product asking
   to be misread. The dot says there is something, the screen says what. */
.notifbtn { position: relative; flex: none; width: 34px; height: 34px; display: grid; place-items: center; border-radius: 999px; color: var(--ink-glass-2); }
.notifbtn svg { width: 18px; height: 18px; }
.notifbtn-dot { position: absolute; top: 5px; right: 6px; width: 7px; height: 7px; border-radius: 999px; background: var(--teal); }
@media (hover: hover) and (pointer: fine) { .notifbtn:hover { color: var(--ink); background: var(--wash-white); } }
@media (hover: hover) and (pointer: fine) { .appnav a:not(.btn):hover { color: var(--ink); } }
@media (max-width: 620px) { .pillrow { height: 52px; padding: 0 12px 0 var(--space-2); gap: 12px; } .appnav { gap: 12px; } .appnav .who { display: none; } }

.appmain { padding: var(--space-6) 0 var(--space-8); }
@media (max-width: 700px) { .appmain { padding: var(--space-4) 0 var(--space-6); } }
.appmain > .wrap > * + * { margin-top: var(--space-4); }
.crumb { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-15); font-weight: 500; color: var(--ink-2); }
.crumb svg { width: 14px; height: 14px; }
@media (hover: hover) and (pointer: fine) { .crumb:hover { color: var(--ink); } }

/* The intake flow's chrome: which question you are on, and a way back. Shared by
   the three intake screens so they read as one sitting, not three pages. */
.stepbar { display: flex; align-items: center; gap: 14px; font-size: var(--text-13); color: var(--ink-2); }
.stepbar .track { flex: 1; height: 4px; border-radius: 999px; background: var(--paper-3); overflow: hidden; max-width: 320px; }
/* The fill is driven by --pct and scales rather than resizing: animating
   width is a layout property and thrashes, and the rings next door already
   take their fraction the same way. */
.stepbar .track i { display: block; width: 100%; height: 100%; background: var(--teal); border-radius: inherit;
                    transform-origin: left center; transform: scaleX(calc(var(--pct, 100) / 100));
                    transition: transform var(--dur-moment) var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .stepbar .track i { transition: none; } }

/* Auth pages: one card in the middle of a quiet page, nothing else to press. */
.authshell { min-height: calc(100dvh - 68px); display: grid; place-items: center; padding: var(--space-6) 0 var(--space-8); }
.authcard { width: 100%; max-width: 420px; }

.workfoot { border-top: 1px solid var(--line); margin-top: var(--space-8); padding: var(--space-3) 0 var(--space-6); }
.workfoot p { font-size: var(--text-13); color: var(--ink-2); max-width: 70ch; }
.workfoot p + p { margin-top: 6px; }

/* Motion, page level. Opacity and 8px, once. */
.js .r { opacity: 0; transform: translateY(8px); transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out); }
.r.in { opacity: 1; transform: none; }
.js .stagger > * { opacity: 0; transform: translateY(8px); transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out); }
.stagger.in > * { opacity: 1; transform: none; }
.stagger.in > :nth-child(2) { transition-delay: 60ms; }
.stagger.in > :nth-child(3) { transition-delay: 120ms; }
.stagger.in > :nth-child(4) { transition-delay: 180ms; }
.stagger.in > :nth-child(5) { transition-delay: 240ms; }
.stagger.in > :nth-child(6) { transition-delay: 300ms; }
@media (prefers-reduced-motion: reduce) {
  .r, .stagger > * { transform: none; transition: opacity 150ms ease; }
  .stagger.in > * { transition-delay: 0ms; }
  .lines li { transform: none !important; transition: opacity 150ms ease; }
  .seg button:active { transform: none; }
}
@media (max-width: 520px) {
  .seg { grid-template-columns: 1fr; }
  .seg button { min-height: 44px; text-align: left; padding: 4px 12px; }
  .total { flex-direction: column; align-items: flex-start; gap: 2px; }
}

/* ---------- 4b. The plan, shared chrome ---------- */
/* Furniture that more than one plan screen uses, so it is defined once here and
   never in a screen's block: the ring, the status pill, and the task row. A
   screen may compose these and may not restyle them. The M2 rail was replaced
   by the sidebar in section 4c and its rules went with it. */

/* The ring says where a stage stands without a sentence: full when every step is
   done, part-filled while it runs, empty before it starts, and a lock when it is
   waiting on something that has not arrived. */
.ring { --pct: 0; position: relative; flex: none; width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center; background: conic-gradient(var(--mint) calc(var(--pct) * 1%), var(--line) 0); }
.ring::after { content: ""; width: 14px; height: 14px; border-radius: 999px; background: var(--paper); }
.ring svg { position: relative; z-index: 1; width: 11px; height: 11px; }
.ring[data-state="done"] { background: var(--mint); color: var(--paper); }
.ring[data-state="done"]::after { display: none; }
.ring[data-state="locked"] { background: var(--paper-3); color: var(--ink-2); }
.ring[data-state="locked"]::after { display: none; }
.ring.lg { width: 44px; height: 44px; }
.ring.lg::after { width: 32px; height: 32px; }
.ring.lg svg { width: 20px; height: 20px; }

/* A status pill always carries a date, because "Done" without a day is not an
   answer a producer can use. It also hugs its text: dropped into a flex or grid
   column it would otherwise stretch the full width and read as a status bar. */
.pill-status { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; font-size: var(--text-13); font-weight: 500; background: var(--paper-3); color: var(--ink-2); white-space: nowrap; width: fit-content; max-width: 100%; align-self: flex-start; justify-self: start; }
/* A pill holding a long status would otherwise refuse to wrap and push its whole
   card past the viewport, so on a phone it is allowed to break across lines. The
   real fix for a pill that needs two lines is shorter copy. */
@media (max-width: 620px) { .pill-status { white-space: normal; } }
.pill-status[data-state="done"] { background: var(--band-mint); color: var(--mint); }
.pill-status[data-state="attention"] { background: var(--band-peach); color: var(--coral-text); }
.pill-status svg { width: 13px; height: 13px; }

/* The task row, in five states. Locked is visible and inert on purpose: a
   producer should see what is coming and what it waits on, not a blank space. */
.taskrow { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.taskrow:first-child { border-top: 0; }
.taskrow .mark { flex: none; width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center; background: var(--paper-3); color: var(--ink-2); margin-top: 2px; }
.taskrow .mark svg { width: 12px; height: 12px; }
.taskrow .body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.taskrow .group { font-size: var(--text-13); color: var(--ink-2); }
.taskrow .what { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.taskrow .waits { font-size: var(--text-13); color: var(--ink-2); }
.taskrow .act { flex: none; align-self: center; }
.taskrow[data-state="done"] .mark { background: var(--band-mint); color: var(--mint); }
.taskrow[data-state="done"] .what { color: var(--ink-2); font-weight: 400; }
.taskrow[data-state="doing"] .mark { background: var(--band-mint); color: var(--mint); }
.taskrow[data-state="signing"] .mark { background: var(--band-peach); color: var(--coral-text); }
.taskrow[data-state="locked"] .what { color: var(--ink-2); font-weight: 500; }
.taskrow[data-state="locked"] .act { display: none; }
/* On a narrow screen the action drops to its own line, indented to clear the
   mark. The indent is the 22px mark plus the row's gap, so the width has to
   subtract it or the button hangs past the row. */
@media (max-width: 620px) {
  .taskrow { flex-wrap: wrap; }
  .taskrow .act { width: calc(100% - 22px - var(--space-2)); align-self: stretch; margin-left: calc(22px + var(--space-2)); }
  .taskrow .act .btn { width: 100%; }
}

/* ---------- 4c. The sidebar, shared chrome (D-047) ---------- */
/* The application's one persistent surface. It carries the production, the plan
   expanded to its four stages, what she owes, what is in her file, and the
   settings that follow her to the next film. Every working screen composes it
   and no screen restyles it, because a nav that changes shape as she moves is a
   nav she has to re-read on every page. Below 900px it collapses into a button
   in the glass header and opens as a sheet over a scrim. */

.appshell { display: grid; grid-template-columns: 236px minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.appshell > * { min-width: 0; }
.appbody > * + * { margin-top: var(--space-4); }
@media (max-width: 1080px) { .appshell { grid-template-columns: 208px minmax(0, 1fr); gap: var(--space-4); } }

.side { position: sticky; top: 88px; display: grid; gap: var(--space-2); align-content: start; font-size: var(--text-15);
        max-height: calc(100dvh - 108px); overflow-y: auto; overscroll-behavior: contain; }

/* The production, first, because every count under it belongs to this film and
   to no other. The state line is the answer to "where is this film", in words. */
.side-prod { display: grid; gap: 2px; padding: var(--space-1) var(--space-1) var(--space-1); border-bottom: 1px solid var(--line); color: var(--ink); }
.side-prod .name { font-family: var(--font-display); font-stretch: 105%; font-weight: 600; font-size: var(--text-18); letter-spacing: -0.015em; line-height: 1.2; }
.side-prod .state { font-size: var(--text-13); color: var(--ink-2); }
.side-prod[aria-current="true"] { background: var(--paper-3); border-radius: 10px; border-bottom-color: transparent; padding-left: var(--space-1); padding-right: var(--space-1); }
@media (hover: hover) and (pointer: fine) { .side-prod:hover .name { color: var(--teal); } }

.side-group { display: grid; gap: 2px; }
/* The group labels are paragraphs, not headings. They sit above the page's
   own h1 in the document, so as headings they put "Documents" ahead of the
   film's name in the outline, and the nav already carries the production's
   name as its label. */
.side-h { font-family: var(--font); font-size: var(--text-13); font-weight: 600; color: var(--ink-2); letter-spacing: 0; padding: 0 var(--space-1) 2px; margin: 0; }
.side-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.side-item { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; }
.side-item > .side-link { flex: 1; min-width: 0; }

.side-link { display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 0 var(--space-1); border-radius: 10px; color: var(--ink-2); font-weight: 500; }
/* The four stage folders sit under the file they belong to, smaller, so the
   count beside "Your file" reads as the total and not as a fifth folder. */
.side-sub .side-link { min-height: 32px; padding-left: 26px; font-size: var(--text-13); }
/* D-051 gave the file's groups their own names, and the longest of them,
   "Permits and location days", lands within a pixel of the 208px sidebar at the
   1080 breakpoint. The sub rows give back eight pixels of indent there rather
   than truncate a name a producer is meant to recognise on sight. */
@media (max-width: 1080px) { .side-sub .side-link { padding-left: 12px; } }
.side-link .label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-link .count { font-family: var(--mono); font-size: var(--text-13); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.side-link[aria-current="true"] { background: var(--paper-3); color: var(--ink); }
.side-link[aria-current="true"] .ring::after { background: var(--paper-3); }
.side-link[data-state="locked"] .label { color: var(--ink-2); }
.side-link svg.lead { width: 16px; height: 16px; flex: none; }
@media (hover: hover) and (pointer: fine) { .side-link:not([aria-current="true"]):hover { background: var(--paper-3); color: var(--ink); } }

/* The badge is the one number in the sidebar she is meant to act on, so it is
   the only thing in here that carries the accent colour. */
.badge { flex: none; min-width: 22px; height: 22px; padding: 0 7px; border-radius: 999px; background: var(--teal); color: var(--teal-ink); font-family: var(--mono); font-size: var(--text-13); font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; justify-content: center; }

/* The info mark answers "what is this stage" without sending her to another
   page for the answer. It is a real button: it opens on a press, closes on
   Escape or on the next press, and nothing about it animates. */
.infomark { flex: none; width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 999px; background: transparent; color: var(--ink-2); cursor: pointer; padding: 0; }
.infomark svg { width: 15px; height: 15px; }
.infomark[aria-expanded="true"] { background: var(--paper-3); color: var(--ink); }
@media (hover: hover) and (pointer: fine) { .infomark:hover { color: var(--ink); } }
/* The note opens in flow, under the row it belongs to, at every width. A
   panel floating out of the column would be clipped the moment the sidebar
   scrolls, and this is a nav, so pushing three rows down for one sentence
   costs nothing. */
.infonote { flex-basis: 100%; margin: 2px 0 6px; padding: 10px 12px; border-radius: var(--radius-float); background: var(--paper-3); font-size: var(--text-13); line-height: 1.5; color: var(--ink); max-width: none; }

.side-foot { padding-top: var(--space-1); border-top: 1px solid var(--line); }

/* The header's menu button. It carries the production name on a phone, because
   the sidebar that would otherwise say it is behind the button. */
.menubtn { display: none; align-items: center; gap: var(--space-1); min-height: 38px; padding: 0 12px 0 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper-2); color: var(--ink); font-family: var(--font); font-size: var(--text-13); font-weight: 500; cursor: pointer; max-width: 46vw; transition: transform var(--dur-press) var(--ease-out); }
.menubtn svg { width: 16px; height: 16px; flex: none; }
.menubtn .label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menubtn:active { transform: scale(0.97); }
.sideclose { display: none; }

.scrim { display: none; }

@media (max-width: 900px) {
  .appshell { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .menubtn { display: inline-flex; }
  .sideclose { display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper-2); color: var(--ink); cursor: pointer; padding: 0; }
  .sideclose svg { width: 16px; height: 16px; }
  .side { position: fixed; top: 0; left: 0; bottom: 0; width: min(320px, 88vw); max-height: none; z-index: 60; background: var(--paper); box-shadow: var(--card-shadow); padding: var(--space-3) var(--space-2) var(--space-6); overflow-y: auto; transform: translateX(-101%); visibility: hidden; transition: transform var(--dur-reveal) var(--ease-out), visibility 0s linear var(--dur-reveal); }
  [data-menu="open"] .side { transform: none; visibility: visible; transition: transform var(--dur-reveal) var(--ease-out), visibility 0s linear 0s; }
  [data-menu="open"] { overflow: hidden; }
  .scrim { display: block; position: fixed; inset: 0; z-index: 55; background: var(--ink); opacity: 0; pointer-events: none; transition: opacity var(--dur-reveal) var(--ease-out); }
  [data-menu="open"] .scrim { opacity: 0.32; pointer-events: auto; }
  .side-link { min-height: 44px; }
  .side-sub .side-link { min-height: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .side { transition: visibility 0s linear var(--dur-reveal); }
  [data-menu="open"] .side { transition: visibility 0s linear 0s; }
  .scrim { transition: none; }
  .menubtn:active { transform: none; }
}

/* The sheet's own header row, only on a phone. */
.side-top { display: none; }
@media (max-width: 900px) { .side-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding-bottom: var(--space-1); } .side-top .logo svg { height: 20px; } }


/* ---------- 4d. The edges, shared chrome (M4) ---------- */
/* Four things every screen owes a producer and one thing no screen may put in
   her way. They live here rather than in a screen block because a producer who
   meets "nothing yet" on two screens should meet the same shape twice. */

/* The empty state. One sentence and one action, and the sentence says what will
   fill this rather than reporting that it is empty. It sits on the page ground
   with a dashed edge, not in a card, because a card around nothing reads as a
   thing that failed to load. */
.emptystate { border: 1px dashed var(--line); border-radius: var(--radius-card); padding: var(--space-6) var(--space-4); display: grid; gap: var(--space-2); justify-items: start; max-width: 62ch; }
.emptystate h3 { font-family: var(--font-display); font-stretch: 105%; font-weight: 600; font-size: var(--text-18); letter-spacing: -0.015em; margin: 0; }
.emptystate p { color: var(--ink-2); margin: 0; max-width: 54ch; }
.emptystate > .btn, .emptystate > .link { margin-top: var(--space-1); }
/* The small one sits inside a screen that is otherwise full, under a group
   heading that already said what the group is, so it drops the heading. */
.emptystate.sm { padding: var(--space-3); gap: var(--space-1); }
.emptystate.sm p { font-size: var(--text-15); }

/* The failure block. Three answers in a fixed order: what happened, whose fault
   it is, and what happens now. The order is the point, so the markup keeps it:
   a state word, a sentence, then the fault line, then what happens now. It is
   the same quiet card as everything else. Coral is on the state word only,
   because a producer reading six of these on the states sheet should not feel
   shouted at, and a red panel is how a form tells someone off. */
.failblock { border: 1px solid var(--line); border-radius: var(--radius-card); padding: var(--space-3); display: grid; gap: var(--space-2); background: var(--paper); max-width: 62ch; }
.failblock-head { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.failblock-head h3 { font-family: var(--font-display); font-stretch: 105%; font-weight: 600; font-size: var(--text-17); letter-spacing: -0.01em; margin: 0; }
.failblock-word { font-size: var(--text-13); font-weight: 600; color: var(--coral-text); flex: none; }
.failblock[data-state="mula"] .failblock-word { color: var(--teal); }
.failblock p { margin: 0; color: var(--ink); }
/* Whose fault, quieter than what happened, because she reads it second. */
.failblock-fault { color: var(--ink-2); font-size: var(--text-15); }
.failblock-do { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-1); }

/* The notification row. Event, production, time, and the way in. The whole row
   is the link, so there is nothing to aim at, and the time is mono and tabular
   so a column of them lines up down the right. */
.notifrow { display: grid; grid-template-columns: 8px minmax(0, 1fr) auto; align-items: baseline; gap: var(--space-2); padding: var(--space-2) var(--space-1); border-radius: 10px; color: var(--ink); border-bottom: 1px solid var(--line); }
.notifrow:last-child { border-bottom: 0; }
.notifrow-dot { width: 8px; height: 8px; border-radius: 999px; background: transparent; align-self: center; }
.notifrow[data-state="unread"] .notifrow-dot { background: var(--teal); }
.notifrow[data-state="clock"] .notifrow-dot { background: var(--coral); }
.notifrow-body { display: grid; gap: 2px; min-width: 0; }
.notifrow-what { font-weight: 500; }
.notifrow-where { font-size: var(--text-13); color: var(--ink-2); }
.notifrow-when { font-family: var(--mono); font-size: var(--text-13); font-variant-numeric: tabular-nums; color: var(--ink-2); flex: none; white-space: nowrap; }
@media (hover: hover) and (pointer: fine) { a.notifrow:hover { background: var(--paper-3); } }
@media (max-width: 520px) {
  .notifrow { grid-template-columns: 8px minmax(0, 1fr); }
  .notifrow-when { grid-column: 2; }
}

/* The clock banner, promoted out of the delivery screen so the city's three
   business days and the distributor's thirty read as the same kind of fact. A
   quiet filled band, never a coral warning: a date that has not passed is not
   at stake, and an item that cannot close until the film shoots is not late. */
.clockbanner { background: var(--paper-3); border-radius: var(--radius-card); padding: var(--space-3); display: grid; gap: var(--space-2); }
.clockbanner-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; }
.clockbanner-head h2 { font-size: var(--text-18); }
.clockbanner p { color: var(--ink); }

/* The dismissible banner. Notices, never in the flow. It closes on a press and
   nothing about it animates, because a notice that slides away draws a second
   look at the thing she just decided to stop looking at. */
.notice { display: flex; align-items: flex-start; gap: var(--space-2); background: var(--tint-mint); border-radius: var(--radius-card); padding: var(--space-2) var(--space-3); }
.notice p { margin: 0; color: var(--ink); font-size: var(--text-15); }
.notice .link { white-space: nowrap; }
.noticeclose { flex: none; width: 28px; height: 28px; margin-left: auto; display: grid; place-items: center; border: 0; border-radius: 999px; background: transparent; color: var(--ink-2); cursor: pointer; padding: 0; }
.noticeclose svg { width: 14px; height: 14px; }
@media (hover: hover) and (pointer: fine) { .noticeclose:hover { color: var(--ink); } }

/* ---------- 5. Per-screen blocks ---------- */
/* Each screen's author writes only inside their own block. */

/* == signup and signin == */
/* Auth chrome: the wordmark alone above the shell, not a link, nothing else to
   press. It stands in for the app header's height so the card still centers in
   the leftover space. */
.authbrand { padding: var(--space-4) 0 0; display: flex; justify-content: center; color: var(--ink); }
.authbrand svg { height: 28px; width: auto; display: block; }

.authcard h1 { margin-bottom: var(--space-1); }
.authcard .sub { margin-bottom: var(--space-4); }

/* The one line back to the other screen. Centered, quiet, after the card.
   A plain link, not `.link`: that class carries a trailing arrow meant for a
   standalone line, and reads wrong stitched into a sentence. */
.authfoot { margin-top: var(--space-3); text-align: center; font-size: var(--text-15); color: var(--ink-2); }
.authfoot a { font-weight: 500; }

/* Sign in's password label shares its row with the reset link, so the two
   actions read together instead of stacking. Same reason to skip `.link` here:
   an arrow next to "Forgot it?" reads as a stray mark beside the label. */
.fieldrow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.fieldrow label { margin-bottom: 0; }
.fieldrow a { font-size: var(--text-13); font-weight: 500; }

/* Sign up explains itself, so a second column earns its place on a wide
   screen. Sign in stays one quiet card and never gets this column. */
.signup-grid { display: grid; grid-template-columns: minmax(0, 420px) minmax(0, 300px); gap: var(--space-6); align-items: start; max-width: 760px; margin: 0 auto; }
.authnext h2 { font-size: var(--text-18); margin-bottom: var(--space-3); }
.authnext ol { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.authnext li { display: flex; gap: var(--space-2); align-items: flex-start; }
.authnext .n { flex: none; color: var(--teal); font-weight: 500; line-height: 1.55; }
.authnext p { font-size: var(--text-15); color: var(--ink-2); }
@media (max-width: 760px) {
  .signup-grid { grid-template-columns: 1fr; max-width: 420px; }
}

/* .authshell centers vertically by default (section 4), which leaves a phone
   screen with a tall gap of nothing above the card. Auth is the only user of
   that shell, so it is overridden here rather than in section 4: top-align
   with a sensible offset instead of centering in the full viewport height. */
@media (max-width: 520px) {
  .authshell { align-items: start; padding-top: var(--space-6); }
}
/* == end signup and signin == */

/* == intake == */
/* The eleven-question sitting: M1 and D1 share one intake. One question fills
   the screen at a time; the stepbar above it says where you are and a way
   back. Three questions are wired for real (a segmented choice, a set of
   counts, and the one a wrong answer costs you later); the rest are shown up
   front as the shape of the whole sitting, so the producer never wonders how
   long this takes. Column stays narrow, phone width or desktop, because a
   short sitting should look short at any size. */
.iq-shell { max-width: 560px; margin: 0 auto; }
.iq-shell h1 { margin-bottom: var(--space-1); }
.iq-lede { max-width: 60ch; }
.iq-panel { transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out); }
.iq-panel.iq-enter { opacity: 0; transform: translateY(8px); }
.iq-panel[hidden] { display: none; }
.iq-panel .stepbar { margin-bottom: var(--space-3); }

/* The up-front list of all eleven. Plain numbers, not checkmarks: nothing on
   this list is answered yet. */
.iq-list { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: grid; gap: 0; }
.iq-list li { display: flex; align-items: baseline; gap: var(--space-2); padding: 10px 0; border-top: 1px solid var(--line); font-size: var(--text-15); color: var(--ink); }
.iq-list li:first-child { border-top: 0; }
.iq-list .n { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-2); font-weight: 500; min-width: 1.6em; }

/* A set of counts: a stepper either side of the number, 44px targets. */
.iq-count { display: grid; gap: var(--space-2); margin-top: var(--space-3); }
.iq-count-row label { display: block; font-size: var(--text-15); font-weight: 500; color: var(--ink); margin-bottom: 6px; }
.iq-count-field { display: flex; align-items: center; gap: 10px; }
.iq-count-field button { width: 44px; height: 44px; flex: none; border-radius: var(--radius-input); border: 1px solid var(--line); background: var(--paper-2); color: var(--ink); font-family: var(--font); font-size: var(--text-18); line-height: 1; cursor: pointer; transition: transform var(--dur-press) var(--ease-out), border-color var(--dur-hover) ease; }
.iq-count-field button:active { transform: scale(0.97); }
.iq-count-field input { width: 76px; min-height: 44px; text-align: center; border-radius: var(--radius-input); border: 1px solid var(--line); background: var(--paper-2); color: var(--ink); font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 1rem; }
@media (hover: hover) and (pointer: fine) { .iq-count-field button:hover { border-color: var(--teal); } }
@media (prefers-reduced-motion: reduce) { .iq-count-field button:active { transform: none; } }
.iq-count-total { margin-top: 2px; font-size: var(--text-15); color: var(--ink-2); }
.iq-count-total b { color: var(--ink); font-weight: 500; }

/* The segmented question's consequence, live under the picker. */
.iq-consequence { margin-top: var(--space-2); padding: 12px 14px; border-radius: var(--radius-input); background: var(--paper-3); font-size: var(--text-15); color: var(--ink); }

/* The load-bearing field's match state, read the same way a placed line
   reads everywhere else in the product. */
.iq-status { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-13); margin-top: 10px; }
.iq-status[hidden] { display: none; }
.iq-status svg { width: 14px; height: 14px; flex: none; }

.iq-actions { margin-top: var(--space-4); }

@media (prefers-reduced-motion: reduce) {
  .iq-panel { transition: opacity 150ms ease; }
  .iq-panel.iq-enter { transform: none; }
}
@media (max-width: 520px) {
  .iq-count-field input { width: 64px; }
}
/* == end intake == */

/* == intake-documents == */
/* Three moments: the drop (a document being read, in three states), the read
   (the clause as it is, next to what it means for the certificate, in plain
   words), and the flag (the one thing that would have cost her). Mono stays
   inside the excerpt and the file name; the translated lines are set in the
   body face on purpose, because the whole point of this screen is that she
   does not have to read the clause to know what it means. */

.docgrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }
@media (max-width: 700px) { .docgrid { grid-template-columns: 1fr; } }

/* The document upload zone. data-state moves empty -> reading -> done. */
.docdrop { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--paper); }
.docdrop[data-state="empty"] { border-style: dashed; background: var(--paper-3); }
@media (hover: hover) and (pointer: fine) { .docdrop[data-state="empty"]:hover { border-color: var(--teal); } }
.docdrop-icon { display: grid; place-items: center; width: 40px; height: 40px; flex: none; border-radius: var(--radius-input); background: var(--paper-3); color: var(--ink-2); }
.docdrop[data-state="empty"] .docdrop-icon { background: var(--paper); }
.docdrop-icon svg { display: none; width: 18px; height: 18px; }
.docdrop[data-state="empty"] .ic-upload { display: block; }
.docdrop:not([data-state="empty"]) .ic-doc { display: block; }
.docdrop[data-state="reading"] .ic-doc { animation: docdrop-pulse 1100ms var(--ease-in-out) infinite; }
@keyframes docdrop-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .docdrop[data-state="reading"] .ic-doc { animation: none; } }

.docdrop-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.docdrop-empty, .docdrop-loaded { display: none; flex-direction: column; gap: 2px; }
.docdrop[data-state="empty"] .docdrop-empty { display: flex; }
.docdrop:not([data-state="empty"]) .docdrop-loaded { display: flex; }
.docdrop-name { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.docdrop-filename { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-13); color: var(--ink-2); }
.docdrop-what { font-size: var(--text-13); color: var(--ink-2); }
.docdrop-choose { position: relative; color: var(--teal); font-weight: 500; cursor: pointer; }
.docdrop-choose input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.docdrop-choose:focus-within { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 3px; }

.docdrop-status { flex: none; display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-13); font-weight: 500; color: var(--ink-2); }
.docdrop-status svg { width: 16px; height: 16px; }
.docdrop-status-reading, .docdrop-status-done { display: none; align-items: center; gap: 6px; }
.docdrop[data-state="reading"] .docdrop-status-reading { display: inline-flex; }
.docdrop[data-state="done"] .docdrop-status-done { display: inline-flex; color: var(--mint); }
@media (max-width: 520px) {
  .docdrop { flex-wrap: wrap; }
  .docdrop-icon { order: 1; }
  .docdrop-status { order: 2; margin-left: auto; }
  .docdrop-body { order: 3; flex-basis: 100%; }
  .docdrop-filename { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
}

/* The read: the clause next to the lines it becomes. Excerpt and file names
   are the only mono on this screen. */
.docread { padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); display: grid; gap: var(--space-3); grid-template-columns: 1fr 1fr; align-items: start; }
.docread h3 { grid-column: 1 / -1; }
.docread .excerpt { overflow-wrap: break-word; }
@media (max-width: 760px) { .docread { grid-template-columns: 1fr; } }

.certline { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.certline li { display: grid; gap: 4px; padding-top: var(--space-2); border-top: 1px solid var(--line); }
.certline li:first-child { padding-top: 0; border-top: 0; }
.certline .k { font-size: var(--text-13); color: var(--ink-2); }
.certline .v { font-size: var(--text-15); color: var(--ink); }

.flagblock .flag { margin-top: var(--space-2); }
/* == end intake-documents == */

/* == intake-number == */
/* The number lands once, in the same narrow column intake and place already
   use: a producer reading a number should never have to hunt for it across a
   wide page. Eight lines build to the total in the site's own .total row.
   Below it, a second, quieter total holds the same eight lines quoted apart.
   It is built down on purpose, a hairline instead of the ink rule, mono at
   body weight instead of the display face, ink-2 throughout, so it reads as
   a fact worth knowing rather than a second offer competing for the eye. */
.numcol { max-width: 600px; margin: 0 auto; }
.numcol > * + * { margin-top: var(--space-4); }
.numcol .lines { margin-top: var(--space-2); }

.numcol .total + .fine { margin-top: var(--space-2); }

.total.quiet { border-top: 1px solid var(--line); margin-top: var(--space-2); padding-top: var(--space-2); }
.total.quiet .k { font-weight: 500; color: var(--ink-2); }
.total.quiet .k small { display: block; font-weight: 400; font-size: var(--text-13); margin-top: 2px; }
.total.quiet .v { font-family: var(--mono); font-weight: 500; font-size: var(--text-17); color: var(--ink-2); flex: none; white-space: nowrap; }

@media (max-width: 520px) {
  .numcol { max-width: 100%; }
}
/* == end intake-number == */

/* == place and bound == */
/* A quiet confirmation, not a checkout: one narrow column, no boxed card around
   the whole page. The receipt card (SimpleClosure) is the one exception, and it
   holds a single sentence and a link, nothing nested inside it. */
.confirm-col { max-width: 560px; margin: var(--space-3) auto 0; }
.confirm-col > * + * { margin-top: var(--space-4); }
.wrap > .crumb { margin-top: var(--space-2); }

/* The receipt: a sentence that closes the placing and a link to the real document. */
.receipt { background: var(--paper-3); border-radius: var(--radius-card); padding: var(--space-3); }
.receipt > * + * { margin-top: var(--space-2); }
.receipt p { color: var(--ink); }

/* What's covered: bold carries only the two signpost labels. */
.covers h2 { margin-bottom: var(--space-1); }
.covers p + p { margin-top: var(--space-1); }
.covers b { color: var(--ink); }

/* What happens next reuses the checks list but in ink-2 with a clock, since none
   of it is done yet. */
.checks.next { margin-top: var(--space-1); }
.checks.next svg { color: var(--ink-2); }
/* == end place and bound == */

/* == productions == */
/* M7: a producer with more than one film lands here, never inside either one
   (the product owner's ruling sends a single-production account straight into
   its plan instead). Every row has to answer, without being asked, where the
   film stands, what it needs from her, and when. The stage rings are the
   rail's own component, unmodified, so a row reads the same way the rail and
   the stage cards do; the count line is the plain arithmetic; the pill-status
   at the end always carries the date. A row is the whole link into the
   production. Nothing inside it is a second control. */
.prodpage > * + * { margin-top: var(--space-4); }
.prodlist-head p { margin-top: var(--space-1); }

.prodlist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }

/* The row is a single block-level link, never a card holding another card. */
.prodrow { display: block; padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); color: var(--ink); transition: border-color var(--dur-hover) ease, background-color var(--dur-hover) ease; }
@media (hover: hover) and (pointer: fine) { .prodrow:hover { border-color: var(--teal); background: var(--paper-3); } }
.prodrow:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

.prodrow-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.prodrow-top h2 { font-size: var(--text-22); }
.prodrow-count { font-size: var(--text-13); color: var(--ink-2); white-space: nowrap; }
.prodrow-sub { margin-top: 2px; font-size: var(--text-15); }

/* The stage strip: only the stages this production's own destination calls
   for, same ring states the rail uses, never redrawn. */
.prodrow-stages { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-3); padding-top: var(--space-2); border-top: 1px solid var(--line); }
.prodrow-stage { display: inline-flex; align-items: center; gap: 8px; font-size: var(--text-13); font-weight: 500; color: var(--ink-2); }

.prodrow-need { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: var(--space-2); flex-wrap: wrap; }
.prodrow-need p { color: var(--ink); font-size: var(--text-15); font-weight: 500; }

/* The way to start a second film. Deliberately a text link, not a button: this
   screen's loudest thing is the film that needs her, not the one that does not
   exist yet. Padded to a full touch target since it carries no button chrome
   to do that on its own. */
.newprod { min-height: 44px; display: inline-flex; align-items: center; }

@media (max-width: 620px) {
  .prodrow-top { flex-direction: column; align-items: flex-start; gap: 2px; }
  .prodrow-need { flex-direction: column; align-items: flex-start; }
}
/* == end productions == */

/* == overview == */
/* The spine. Two problems solved here rather than decorated: one line at the
   top that says what is owed and when, so a producer never has to read all
   four cards to know her next move, and a stage card whose ring, pill and
   copy tell the truth about where it stands (in flight, not started, or
   locked) without four different background colours doing the talking. */

.ovcol { min-width: 0; }
.ovcol > * + * { margin-top: var(--space-4); }
.ovhead h1 { margin-bottom: var(--space-1); }

/* The one thing. A quiet strip between two hairlines, not a banner: the
   pill carries the date, one sentence carries the task, a second sentence
   accounts for the rest without listing it. It links into the queue instead
   of trying to be the queue. */
.owed { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: var(--space-3) 0; display: grid; gap: var(--space-1); }
.owed h2 { margin-bottom: 2px; }
.owed-lede { font-size: var(--text-18); color: var(--ink); font-weight: 500; }
.owed-more { font-size: var(--text-15); }
.owed > .link { margin-top: 2px; }

/* The stage card. Name, a status pill with a date, a ring for how far it has
   gone, its phases as rows, one full-width action. Cards never take a
   background tint to say where they stand; the ring's fill, the pill's word,
   and the phase copy do that instead. */
.stagecards { display: grid; gap: var(--space-3); }
.stagecard { border: 1px solid var(--line); border-radius: var(--radius-card); padding: var(--space-3); }
.stagecard-head { display: flex; align-items: flex-start; gap: var(--space-2); }
.stagecard-title { flex: 1; min-width: 0; display: grid; gap: 6px; }
.stagecard-title h2 { margin: 0; }
.stagecard-frac { flex: none; color: var(--ink-2); font-size: var(--text-15); padding-top: 4px; }
/* A locked card reads recessed through its own name, not a tint. */
.stagecard[data-state="locked"] .stagecard-title h2 { color: var(--ink-2); }
/* The pill stays a state and a date; the sentence that used to live inside it
   reads better here, under the header and above the phases it explains. */
.stagecard-lede { font-size: var(--text-15); color: var(--ink); margin-top: var(--space-2); }

.phaserows { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: grid; gap: 0; }
.phaserow { display: flex; gap: var(--space-2); align-items: flex-start; padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.phaserow:first-child { border-top: 0; padding-top: 0; }
.phaserow-body { flex: 1; min-width: 0; display: grid; gap: 4px; }
.phaserow-name { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.phaserow-left { font-size: var(--text-15); color: var(--ink-2); }
.phaserow-left .pill-status { margin-right: 6px; vertical-align: middle; }
.phaserow-link { margin-top: 2px; }

.stagecard .btn-wide { margin-top: var(--space-3); }

@media (max-width: 520px) {
  .stagecard-frac { display: none; }
}
/* == end overview == */

/* == stage == */
/* The Covered stage: three phases as numbered columns, each a vertical
   timeline of step cards, the SimpleClosure structure in Mula's own grammar.
   The package is finished and closes on a receipt; certificates is four of
   five out; workers' comp has barely started. The layout has to make those
   three different moments legible without leaning on color to do it, so the
   difference between done and waiting is a filled mark plus quieter type
   against a plain mark plus full ink, not a palette. Mint stays reserved for
   the word a status pill actually says; nothing here is at stake, so coral
   never appears. */

.stagehead > * + * { margin-top: var(--space-1); }
.stagehead-meta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-2); }

/* The numbered phase column. Three side by side once there is room, divided
   by a hairline rather than boxed into cards of their own. Below the width
   where three columns stop being readable they stack as full width sections,
   read top to bottom in the same order a producer would ask about them, each
   opening with the same numbered heading it had beside its neighbors. */
.phasegrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); align-items: start; }
.phasecol { min-width: 0; padding-left: var(--space-4); border-left: 1px solid var(--line); }
.phasecol:first-child { padding-left: 0; border-left: 0; }
@media (max-width: 900px) {
  .phasegrid { grid-template-columns: 1fr; gap: var(--space-6); }
  .phasecol { padding-left: 0; border-left: 0; padding-top: var(--space-4); border-top: 1px solid var(--line); }
  .phasecol:first-child { padding-top: 0; border-top: 0; }
}

.phasecol-head { display: flex; align-items: flex-start; gap: var(--space-2); margin-bottom: var(--space-3); }
.phasecol-num { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 999px; border: 1px solid var(--line); font-family: var(--font-display); font-weight: 600; font-size: var(--text-15); color: var(--ink); }
.phasecol-head h2 { font-size: var(--text-18); }
.phasecol-count { font-size: var(--text-13); color: var(--ink-2); margin-top: 2px; }

/* The step timeline: a plain line joining every mark, so a column reads as
   one thread of work moving down the page instead of a stack of unrelated
   rows that happen to share a heading. */
.steptimeline { position: relative; list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.steptimeline::before { content: ""; position: absolute; left: 10px; top: 11px; bottom: 11px; width: 1px; background: var(--line); }
.steptimeline li { position: relative; }

/* The step card: a mark, what the step is, the counterparty when it has one,
   and its state and date together in the shared status pill. A finished step
   drops its mark and its title into the quieter ink-2 weight; open and locked
   steps keep full ink, so what still needs a look reads heavier on the page
   than what is already handled, the way a producer would actually scan it. */
.stepcard { position: relative; z-index: 1; display: flex; align-items: flex-start; gap: 12px; min-height: 44px; padding: 9px var(--space-1); margin: 0 calc(var(--space-1) * -1); border-radius: var(--radius-input); color: inherit; }
@media (hover: hover) and (pointer: fine) { .stepcard:hover { background: var(--paper-3); } }
.stepcard-mark { flex: none; margin-top: 1px; width: 22px; height: 22px; border-radius: 999px; display: grid; place-items: center; background: var(--paper-3); color: var(--ink-2); }
.stepcard-mark svg { width: 12px; height: 12px; }
.stepcard[data-state="done"] .stepcard-mark { background: var(--band-mint); color: var(--mint); }
.stepcard[data-state="done"] .stepcard-what { color: var(--ink-2); font-weight: 400; }
.stepcard-body { flex: 1; min-width: 0; display: grid; gap: 4px; padding-top: 2px; }
.stepcard-what { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.stepcard-who { font-size: var(--text-13); color: var(--ink-2); }
.stepcard-waits { font-size: var(--text-13); color: var(--ink-2); }

/* The phase receipt: one sentence that closes a finished phase and a link to
   the real document, sitting under the timeline rather than boxed as a card
   inside the column. The indent matches the mark and gap above it, so it
   reads as the last thing the thread produced, not a new element. */
.phase-receipt { margin-top: var(--space-2); padding-left: 34px; }
.phase-receipt p { color: var(--ink); }
.phase-receipt .link { margin-top: 6px; }
/* == end stage == */

/* == step == */
/* The phase detail page (BRIEF-M2 calls the row inside it a "step"; the shared
   component that renders each one is the section 4b `.taskrow`). Composed
   entirely from section 4b: the rail, the status pill, the task row. What is
   new here is the two-column layout and the step info panel itself, the
   reason this screen exists (reference point 4, BRIEF-M2's "and the voice").

   The phone layout: this phase only ever has a few steps, short rows, so the
   panel sits in normal document order right after the task list rather than
   above it or behind a disclosure. That keeps the tasks the first thing on
   the screen (never pushed down by a paragraph of prose) without burying the
   panel under a long list it would actually need to be hidden behind. A
   jump-ahead teaser line was the other option and was rejected: dangling a
   "why this matters, see below" hook is the manufactured-curiosity tic
   docs/VOICE.md bans, so the panel earns its place with its own heading and
   full-weight type instead of a trick to get it read. */

.stephead { display: grid; gap: var(--space-1); }
.stepmeta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-size: var(--text-13); color: var(--ink-2); }
.stepmeta time { font-weight: 500; color: var(--ink); }

.stepgrid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-4); align-items: start; }
.tasklist { list-style: none; margin: 0; padding: 0; }

/* The quiet panel: the section's own paper-3 fill and card radius, no border,
   nothing nested inside it. Body copy is the page's own ink-2 paragraph, not
   a special color, because the point is that it reads like a person talking,
   not a callout box shouting for attention. */
.steppanel { background: var(--paper-3); border-radius: var(--radius-card); padding: var(--space-3); display: grid; gap: var(--space-2); }
.steppanel h2 { font-size: var(--text-18); }
.steppanel .mono { color: var(--ink); }

@media (max-width: 760px) {
  .stepgrid { grid-template-columns: 1fr; }
}
/* == end step == */

/* == tasks == */
/* The queue: every task across the whole plan, counted once by state instead
   of by stage. Five tabs, not a filter and not five sections stacked on one
   page: a producer checking this between setups needs to land on one list,
   not scroll past fifteen locked rows and twelve finished ones to find the
   four things that need her today. The queue opens on To do, never Locked,
   which would be a wall of things she cannot touch, and never Completed,
   which looks backward instead of at what is next. */
.queuetabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); overflow-x: auto; -webkit-overflow-scrolling: touch; }
.queuetabs button { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 var(--space-2); border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px; background: transparent; font-family: var(--font); font-size: var(--text-15); font-weight: 500; color: var(--ink-2); white-space: nowrap; cursor: pointer; transition: color var(--dur-hover) ease, border-color var(--dur-hover) ease; }
.queuetabs button[aria-selected="true"] { color: var(--ink); border-color: var(--teal); }
.queuetabs .n { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: var(--text-13); color: var(--ink-2); background: var(--paper-3); border-radius: 999px; min-width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; padding: 0 6px; }
@media (hover: hover) and (pointer: fine) { .queuetabs button:not([aria-selected="true"]):hover { color: var(--ink); } }
@media (prefers-reduced-motion: reduce) { .queuetabs button { transition: none; } }

.tasklist { list-style: none; margin: 0; padding: 0; }
.tasklist .taskrow .pill-status { margin-top: 2px; }

/* Task detail: one narrow column, the same width discipline as the number and
   placing screens, because this is also a page meant to be read, not scanned. */
.taskcol { max-width: 640px; }
.taskcol > * + * { margin-top: var(--space-4); }
/* == end tasks == */

/* == file == */
/* The file: every document and certificate the plan produces, grouped by the
   same four stages the rail already uses, so a producer never has to learn a
   second structure to find something. Certificates live inside their stage's
   group rather than a separate list, because a certificate is a document like
   any other and singling it out would say otherwise. A row never claims a
   date it does not have: "In the file" and "Out for signature" earn a plain
   date underneath, a row that is still waiting on someone else just says what
   it is waiting on and leaves it there. */

.fileactions { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); }

.filegroup { scroll-margin-top: 100px; }
.filegroup-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); padding-bottom: var(--space-1); border-bottom: 1px solid var(--line); }
.filegroup-count { display: inline-flex; align-items: center; gap: 4px; font-size: var(--text-13); color: var(--ink-2); white-space: nowrap; }
.filegroup-count svg { width: 12px; height: 12px; }
.filegroup > .fine { margin-top: var(--space-2); }

.filerows { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.filerow { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--line); color: inherit; }
.filerows li:first-child .filerow { border-top: 0; padding-top: 0; }
.filerow-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.filerow-name { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.filerow-note { font-size: var(--text-13); color: var(--ink-2); max-width: 52ch; }
.filerow[data-state="done"] .filerow-name { color: var(--ink-2); font-weight: 400; }
.filerow-state { flex: none; display: grid; justify-items: end; gap: 2px; text-align: right; }
.filerow-when { font-size: var(--text-13); color: var(--ink-2); white-space: nowrap; }
a.filerow { border-radius: var(--radius-input); margin: 0 calc(var(--space-1) * -1); padding-left: var(--space-1); padding-right: var(--space-1); transition: background-color var(--dur-hover) ease; }
@media (hover: hover) and (pointer: fine) { a.filerow:hover { background: var(--paper-3); } }

@media (max-width: 560px) {
  .filerow { flex-direction: column; align-items: flex-start; gap: 6px; }
  .filerow-state { justify-items: start; text-align: left; }
}

/* The upload and template sections on "Add to the file" share the page's
   default rhythm, tightened: a heading and its one sentence sit closer
   together than the space between unrelated sections does. */
.filenew-section > * + * { margin-top: var(--space-2); }
.filenew-section h2 + p { margin-top: 4px; }

.tplrows { list-style: none; margin: 0; padding: 0; }
.tplrow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.tplrows li:first-child { border-top: 0; padding-top: 0; }
.tplrow-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.tplrow-name { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.tplrow-what { font-size: var(--text-13); color: var(--ink-2); }
.tplrow-act { flex: none; display: flex; align-items: center; }
/* .pill-status sets its own display, which otherwise beats the browser's
   default [hidden] rule once a class and an attribute both claim it. Section
   4b never needed this since nothing there toggled a pill with the hidden
   attribute; this screen's "Send it" does, so the fix lives here. */
.tplrow-act .pill-status[hidden] { display: none; }

@media (max-width: 560px) {
  .tplrow { flex-wrap: wrap; }
  .tplrow-act { width: 100%; }
  .tplrow-act .btn { width: 100%; }
}
/* == end file == */

/* == certificates == */
/* Screen 18 lists every certificate this production has sent and where it
   stands, one row per counterparty. Screen 20 opens one, built for
   COI-LT-0002, the Vernon warehouse, because a correction is the case that
   actually tests whether this page tells the truth. BRIEF-M2's ruling binds
   both: a correction never reopens the step. The certificate was issued, so
   it stays counted as issued here, and its row simply carries a second,
   honest state layered on top of that rather than replacing it. */

.certhead > * + * { margin-top: var(--space-1); }
.certhead .btn { margin-top: var(--space-2); }

/* The row is a single block-level link, the same grammar `.prodrow` and
   `.stepcard` already use: counterparty, the wording it carries, the time it
   went out, its state. Three columns once there is room; below 700px the row
   stacks so nothing scrolls sideways to be read, which BRIEF-M3 asks for by
   name. */
.certlist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.certrow { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); color: inherit; transition: border-color var(--dur-hover) ease, background-color var(--dur-hover) ease; }
.certrow-who { display: grid; gap: 2px; min-width: 0; }
.certrow-who h2 { font-size: var(--text-18); }
.certrow-id { font-size: var(--text-13); color: var(--ink-2); }
.certrow-wording { font-size: var(--text-15); color: var(--ink-2); }
.certrow-meta { display: flex; align-items: center; gap: var(--space-2); justify-self: end; }
.certrow-time { font-size: var(--text-15); color: var(--ink-2); white-space: nowrap; }
@media (hover: hover) and (pointer: fine) { .certrow:hover { border-color: var(--teal); background: var(--paper-3); } }
.certrow:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
@media (max-width: 700px) {
  .certrow { grid-template-columns: 1fr; gap: 6px; }
  .certrow-meta { justify-self: start; }
}

/* Certificate detail. The document mock and the wording it carries sit in the
   main column; who received it and the one action sit in a quiet aside,
   the same two-column frame `.stepgrid` already established. */
.certdethead { display: grid; gap: var(--space-1); }
.certdet-meta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.certdet-id { font-size: var(--text-15); color: var(--ink-2); }

.certdetgrid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-4); align-items: start; }
.certdetmain > * + * { margin-top: var(--space-4); }
@media (max-width: 760px) { .certdetgrid { grid-template-columns: 1fr; } }

/* The document itself, built from components rather than a picture: a label
   header and a plain field list, mono on the values the way every product
   mock in the system already sets a document's own figures and names. */
.certdoc { border: 1px solid var(--line); border-radius: var(--radius-card); overflow: hidden; }
.certdoc-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-2) var(--space-3); background: var(--paper-3); }
.certdoc-label { font-size: var(--text-13); font-weight: 500; color: var(--ink-2); }
.certdoc-num { font-size: var(--text-13); color: var(--ink-2); }
.certdoc-fields { margin: 0; padding: var(--space-3); display: grid; gap: var(--space-2); }
.certdoc-row { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: var(--space-2); margin: 0; padding-top: var(--space-2); border-top: 1px solid var(--line); }
.certdoc-row:first-child { padding-top: 0; border-top: 0; }
.certdoc-row dt { font-size: var(--text-13); color: var(--ink-2); }
.certdoc-row dd { margin: 0; font-family: var(--mono); font-size: var(--text-15); color: var(--ink); }
@media (max-width: 520px) { .certdoc-row { grid-template-columns: 1fr; gap: 2px; } }

/* The wording it carries: the line as the counterparty asked for it, then
   what it means, so a legal phrase is never printed and left to speak for
   itself. The line added this afternoon carries the shared status pill
   rather than its own colour, so coral still only ever labels a state. */
.wordlines { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.wordlines li { padding-top: var(--space-2); border-top: 1px solid var(--line); }
.wordlines li:first-child { padding-top: 0; border-top: 0; }
.wordline-term { color: var(--ink); font-weight: 500; }
.wordline-term .pill-status { margin-left: 8px; vertical-align: middle; }
.wordline-mean { margin-top: 2px; font-size: var(--text-15); }

/* Who received it: a quiet aside, the section's own paper-3 fill and card
   radius, nothing nested inside it, the same grammar `.steppanel` set. */
.certdetpanel { background: var(--paper-3); border-radius: var(--radius-card); padding: var(--space-3); display: grid; gap: var(--space-3); }
.certdetpanel h2 { font-size: var(--text-18); }
.recvlines { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.recvlines li { display: grid; gap: 2px; padding-top: var(--space-2); border-top: 1px solid var(--line); }
.recvlines li:first-child { padding-top: 0; border-top: 0; }
.recv-who { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.recv-when { font-size: var(--text-13); color: var(--ink-2); }
.certdetpanel .btn + .btn { margin-top: 2px; }
.resend-note { color: var(--mint); }
/* == end certificates == */

/* == request == */
/* Screen 19 requests a certificate two ways: pick a counterparty, or forward
   what they sent. Both live on one page behind the `.seg` method switch
   app.js already drives, so only one is ever in view. The counterparty list
   reuses `.partyrow-who`, `.ctpyrow-lead` and `.pill-status` from `==
   people ==` rather than inventing a second look for the same fact, and each
   option is a native radio so the row works the same for a mouse, a keyboard
   and a screen reader; the input is visually hidden and the label carries
   the click target and the focus ring. The preview beside it keeps all seven
   counterparties' wording in the page at once (screen 19's own script shows
   only the checked one), reusing `.certline` from `== intake-documents ==`
   for the same term-then-meaning shape that screen already set. Screen 21
   is the one new shape here: the before-and-after a correction actually is,
   stacked below 620px so a wording change is never a value someone has to
   scroll sideways to read. */

.partypick { display: grid; gap: var(--space-2); }
.partyopt { position: relative; display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); cursor: pointer; transition: border-color var(--dur-hover) ease, background-color var(--dur-hover) ease; }
.partyopt input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.partyopt:has(input:checked) { border-color: var(--teal); background: var(--paper-3); }
.partyopt:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .partyopt:hover { border-color: var(--teal); } }
@media (max-width: 700px) {
  .partyopt { grid-template-columns: 1fr; gap: 6px; }
}
@media (prefers-reduced-motion: reduce) { .partyopt { transition: none; } }

/* The preview panel's own rhythm: a name, its wording, when it goes out, then
   one primary action or, for a counterparty already carrying a certificate,
   a plain link back to it instead. Never both in the same view. A class that
   sets its own `display` has to restate the default `[hidden]` rule or the
   attribute loses the tie, the same fix `== intake ==` already made for
   `.iq-panel`. The two method panels take the same fix, scoped to their own
   ids rather than touching `.certdetgrid`, which `== certificates ==` owns. */
.reqpreview { display: grid; gap: var(--space-2); }
.reqpreview[hidden] { display: none; }
.reqpreview h3 { font-size: var(--text-18); }
.reqpreview .btn { margin-top: 2px; }
#panel-pick[hidden], #panel-forward[hidden] { display: none; }

/* Before and after, the whole of what screen 21 has to prove. Two columns
   once there is room, plain paper-3 cards with no state colour of their own,
   because a wording line is neither done nor at stake until it is actually
   sent; the pill above it already carries that. */
.diffgrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.diffcol { padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--paper-3); }
.diffcol-label { display: block; font-size: var(--text-13); color: var(--ink-2); margin-bottom: 4px; }
.diffcol-value { margin: 0; font-size: var(--text-15); color: var(--ink); font-weight: 500; }
@media (max-width: 620px) { .diffgrid { grid-template-columns: 1fr; } }
/* == end request == */

/* == people == */
/* Screen 22 lists two groups Dani thinks of separately: the seven
   counterparties who each want their own wording before they let her in the
   door, and her own people, who already signed. The counterparty row is the
   gap named in the plan. It carries a fact no earlier row shape needed to
   show: a want, a lead time, and a certificate state, together, because the
   lead time is the reason this screen exists (a same-day rental house and a
   five-day location are different kinds of urgency). It borrows the card,
   border and hover language `.certrow` already shipped in `== certificates
   == ` rather than inventing a second look for the same kind of fact, so the
   two lists of counterparties in this product read as one family. Screen
   23's read reuses `.excerpt` and `.certline` from `== intake-documents ==`
   for the same reason: the lease says what it says no matter which screen
   is quoting it, and the certificate list at its foot is the same `.certrow`
   again, one row instead of five. */

.peoplesec > * + * { margin-top: var(--space-2); }
.peoplesec .ctpylist,
.peoplesec .pplrow-list,
.peoplesec .partyread,
.peoplesec .certlist { margin-top: var(--space-3); }
.peoplesec .btn { margin-top: var(--space-3); }

/* The counterparty row. Three columns once there is room: who and what they
   want, the lead time as its own stat, and the certificate's own state pill.
   Below 700px it stacks, same breakpoint `.certrow` uses, so nothing on this
   screen ever asks a producer to scroll sideways to read a value. */
.ctpylist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.ctpyrow { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; padding: var(--space-3); border: 1px solid var(--line); border-radius: var(--radius-card); color: inherit; transition: border-color var(--dur-hover) ease, background-color var(--dur-hover) ease; }
@media (hover: hover) and (pointer: fine) { .ctpyrow:hover { border-color: var(--teal); background: var(--paper-3); } }
.ctpyrow:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.ctpyrow-lead { display: grid; gap: 2px; }
.ctpyrow-lead .k { font-size: var(--text-13); color: var(--ink-2); }
.ctpyrow-lead .v { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
@media (max-width: 700px) {
  .ctpyrow { grid-template-columns: 1fr; gap: 6px; }
  .ctpyrow-lead { display: flex; gap: 6px; align-items: baseline; }
}
@media (prefers-reduced-motion: reduce) { .ctpyrow { transition: none; } }

/* Shared by both lists on this screen: a name, and the one line under it
   that says what they want or what they carry. */
.partyrow-who { display: grid; gap: 2px; min-width: 0; }
.partyrow-who h3 { font-size: var(--text-18); font-weight: 600; color: var(--ink); letter-spacing: -0.01em; display: flex; align-items: baseline; gap: 8px; }
.partyrow-who h3 .mono { font-weight: 400; color: var(--ink-2); font-size: var(--text-15); }
.partyrow-who p { font-size: var(--text-15); color: var(--ink-2); }

/* Her own people. Not a link: nothing on this prototype is behind a role and
   a count yet, so the row stays a plain fact instead of a promise to click
   through to something that is not built. Same rhythm as `.taskrow`. */
.pplrow-list { list-style: none; margin: 0; padding: 0; }
.pplrow { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.pplrow:first-child { border-top: 0; }
.pplrow .partyrow-who { flex: 1; }
.pplrow .pill-status { flex: none; }
@media (max-width: 520px) {
  .pplrow { flex-wrap: wrap; }
  .pplrow .pill-status { margin-top: 4px; }
}

/* Screen 23's read: the clause, then the one line worth saying out loud,
   stacked rather than the two-column frame `== intake-documents ==` uses for
   its pair of documents, because this screen only ever holds one clause and
   one flagged line, not two things side by side. */
.partyread { display: grid; gap: var(--space-3); }

/* Screen 23 already opened with an h1 and its own section h2s, so its one
   reused `.certrow` names itself with an h3 instead of `== certificates
   == `'s h2. Sized to match exactly, so the row looks identical wherever it
   appears. */
.peoplesec .certrow-who h3 { font-size: var(--text-18); line-height: 1.15; letter-spacing: -0.025em; }
/* == end people == */

/* == delivery == */
/* The one screen with two states on one page. State one is the empty
   intake: drop the schedule, or pick a distributor type when it is not in
   hand yet. State two is the match: the fourteen items on the schedule,
   read against the file. Composed almost entirely from what already
   ships. `.docdrop` (== intake-documents ==) and `.seg` (base component)
   need no new CSS to work here; `.filegroup` and `.filerow` (== file ==)
   give the matched rows the same grouped shape the file already uses, so
   a producer who knows that screen does not have to learn a second one.
   The clock banner is the one genuinely new component, because BRIEF-M3
   asks it to carry a fact no earlier banner has to: which two items on
   the list cannot close before the film has even shot, so a screen that
   showed them as overdue during prep would be a screen she stops
   trusting. */

.delintake { display: grid; gap: var(--space-3); margin-top: var(--space-3); max-width: 560px; }
.delor { margin: 0; text-align: center; font-size: var(--text-13); color: var(--ink-2); }
.delseg > p { margin: 0 0 var(--space-2); font-size: var(--text-15); color: var(--ink); }

/* The dropzone doubles as a button in this prototype: pressing it stands
   in for a real upload, the same way pressing the segmented picker stands
   in for a real pick. `.docdrop` was built as a plain container, so the
   pointer cursor and focus ring a real control needs are added here,
   scoped to the role this page gives it, and never touch the shared rule. */
.docdrop[role="button"] { cursor: pointer; }
.docdrop[role="button"]:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* The match, grouped by what it needs from her rather than by stage, since
   this list is about the distributor's ask, not the plan's own four
   stages. Groups sit further apart than the rows inside them do. */
.delgroups > * + * { margin-top: var(--space-4); }

/* The one orchestrated moment: all fourteen rows arrive together across
   every group. `window.mula.flow()` is called once on the whole container,
   so the indices run in document order instead of restarting per group.
   Scoped to this page's own rows, so `== file ==`'s own list never moves. */
.delgroups .filerows.flow li { transition: opacity var(--dur-moment) var(--ease-out), transform var(--dur-moment) var(--ease-out); }
.delgroups .filerows.flow li.pending { opacity: 0; transform: translateY(6px); }
@media (prefers-reduced-motion: reduce) {
  .delgroups .filerows.flow li { transform: none; transition: opacity 150ms ease; }
}

.delclose { max-width: 64ch; }

@media (max-width: 520px) {
  .delintake { max-width: none; }
}
/* == end delivery == */

/* == settings == */
/* Screen 25 is one form, not four cards: the insured name, who hears about
   this film and how, and what a returning producer never has to re-answer.
   `.form`, `.field`, `.pplrow` and `.certline` are unchanged; the two new
   pieces are the name-match check (a real component, on the sheet) and the
   notification switch, built on the same button-plus-aria-pressed toggle the
   destination picker already uses rather than a second field family. */

.setcol { max-width: 640px; }
.setsec > * + * { margin-top: var(--space-2); }
.setsec .field,
.setsec .namematch,
.setsec .preflist { margin-top: var(--space-3); }
.setsec .pplrow-list + .field { margin-top: var(--space-3); }

/* The name-match check. Composes `.certdetpanel`'s quiet paper-3 frame and
   `.certline`'s own k/v rows rather than inventing either. The mark and the
   line follow the company field live; the stake sentence underneath never
   changes; a mismatch does not make the cost any less true when it is still
   matching. */
.namematch-head { display: flex; align-items: flex-start; gap: var(--space-2); }
.namematch-mark { flex: none; width: 28px; height: 28px; border-radius: 999px; display: grid; place-items: center; background: var(--band-mint); color: var(--mint); margin-top: 2px; }
.namematch-mark svg { width: 15px; height: 15px; }
.namematch-line { font-size: var(--text-17); font-weight: 500; color: var(--ink); }
.namematch .certline { margin: var(--space-2) 0 0 44px; }
.namematch-stake { margin: 0 0 0 44px; }
.namematch[data-state="mismatch"] .namematch-mark { background: var(--band-peach); color: var(--coral-text); }
.namematch[data-state="mismatch"] .namematch-line { color: var(--coral-text); }
@media (max-width: 520px) {
  .namematch .certline, .namematch-stake { margin-left: 0; }
}

/* Notification preferences. A row is a name, one sentence of what it does,
   and a switch. The switch reuses the segmented picker's own aria-pressed
   convention rather than a checkbox input, so the product keeps one toggle
   idiom. Colour swaps instantly with the attribute; only the knob's position
   and the switch's own press animate, and only on transform. */
.preflist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.prefrow { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--line); }
.preflist > .prefrow:first-child { padding-top: 0; border-top: 0; }
.prefrow-body { display: grid; gap: 2px; min-width: 0; }
.prefrow-name { font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.prefrow-what { font-size: var(--text-15); color: var(--ink-2); }
.prefswitch { flex: none; width: 44px; height: 26px; margin-top: 2px; border-radius: 999px; border: 1px solid var(--line); background: var(--paper-3); padding: 2px; cursor: pointer; display: inline-flex; align-items: center; transition: transform var(--dur-press) var(--ease-out); }
.prefswitch:active { transform: scale(0.97); }
.prefswitch[aria-pressed="true"] { background: var(--teal); border-color: var(--teal); }
.prefswitch .knob { width: 20px; height: 20px; border-radius: 999px; background: var(--paper); transform: translateX(0); transition: transform var(--dur-press) var(--ease-out); }
.prefswitch[aria-pressed="true"] .knob { transform: translateX(18px); }
@media (prefers-reduced-motion: reduce) { .prefswitch, .prefswitch .knob { transition: none; } .prefswitch:active { transform: none; } }

/* Saving. One primary button for the whole form; the confirmation is the
   same opacity-and-8px reveal every other one-time moment in this product
   uses, triggered on submit instead of on scroll into view. */
.setsave { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.savednote { opacity: 0; transform: translateY(8px); transition: opacity var(--dur-reveal) var(--ease-out), transform var(--dur-reveal) var(--ease-out); }
.savednote.show { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .savednote { transition: opacity 150ms ease; transform: none; } }
/* == end settings == */

/* ---------- 5b. Milestone 4 blocks ---------- */

/* == permits == */
/* Screen 26, permit filing. The Permitted stage has one phase and one honest
   subject: dates. This block composes .stagehead and .stagehead-meta
   (== stage ==), .clockbanner, .flag and .failblock (4d and section 3),
   and .tasklist / .taskrow (4b) unchanged. The two new things are the day
   column, whose counts sit in one mono file so the nine the heading claims can
   be added up, and the disclosure that holds the failure state off to the
   side until she asks for it: a page that is mostly a plan she can hold
   should not open with a card about the plan going wrong. */

.permitwhatif { margin-top: var(--space-3); }
.permitwhatif > summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; color: var(--teal); font-weight: 500; font-size: var(--text-15); }
.permitwhatif > summary:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 6px; }
.permitwhatif[open] > summary { color: var(--ink); margin-bottom: var(--space-2); }

/* The day counts are the arithmetic the heading claims, so they sit in one
   right-aligned mono column with the nine underneath rather than stacked under
   each location, where a producer cannot add them up. */
.daylist { list-style: none; margin: var(--space-2) 0 0; padding: 0; max-width: 420px; }
.daylist li { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); min-height: 36px; border-bottom: 1px solid var(--line); }
.daylist .k { color: var(--ink); }
.daylist .v { font-size: var(--text-15); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.daylist-total { border-bottom: 0; font-weight: 600; }
.daylist-total .k, .daylist-total .v { color: var(--ink); }
/* == end permits == */

/* == comp == */
/* Screen 27, workers' comp. step.html carries the three-task list and the
   generic step frame; this screen sits underneath it and answers M8's real
   question, "do I need this if nobody's an employee," in the first thing she
   reads, then the money and the routing. A narrow reading column, the same
   discipline .taskcol already set for the task detail page, because this is
   meant to be read once and acted on, not scanned like a list. */
.compdoc { max-width: 640px; }
.compdoc > * + * { margin-top: var(--space-4); }
.comphead > * + * { margin-top: var(--space-1); }
.compdoc section > * + * { margin-top: var(--space-2); }

/* The one-line other branch: a production that pays nobody. A hairline sets
   it apart from the main answer without boxing it as a card. */
.comp-branch { border-top: 1px solid var(--line); padding-top: var(--space-2); color: var(--ink-2); }

.comp-cta { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
/* == end comp == */

/* == music == */
/* Screen 28: two states on one page, the same shape == delivery == uses,
   for the same reason. State one composes .docdrop (== intake-documents ==)
   and .failblock (base, section 4d) unchanged. State two composes .filegroup
   and .filerow (== file ==), .diffgrid (== request ==) and .iq-list (base)
   unchanged. The two festival-only rows keep no data-state on .filerow
   itself, so their names stay full ink weight rather than the dimmed
   "done" treatment the other ten cues carry; the pill alone carries the
   coral. */
.musicintake { display: grid; gap: var(--space-3); margin-top: var(--space-3); max-width: 560px; }
.musicstart .failblock { margin-top: var(--space-3); max-width: 560px; }

.cuecheck > * + * { margin-top: var(--space-4); }

/* The one orchestrated moment: all twelve rows arrive together, 60ms
   apart, the same convention == delivery == set for its own fourteen.
   Scoped to this page's own rows so == file =='s list never moves. */
.cuecheck .filerows.flow li { transition: opacity var(--dur-moment) var(--ease-out), transform var(--dur-moment) var(--ease-out); }
.cuecheck .filerows.flow li.pending { opacity: 0; transform: translateY(6px); }
@media (prefers-reduced-motion: reduce) {
  .cuecheck .filerows.flow li { transform: none; transition: opacity 150ms ease; }
}

.cueflag .diffgrid { margin: var(--space-3) 0; }
.cueflag .iq-list { max-width: 560px; margin-top: var(--space-2); }
/* == end music == */

/* == reports == */
/* Screens 29 and 30, D8 and D9, share this block because they share one
   idea: both are a wait a producer can actually plan around once the
   arithmetic is laid out. Composed almost entirely from what already ships.
   `.filegroup` and `.filerow` (== file ==) give the reports and the
   attorney's document manifest the same grouped shape the file already
   uses, so a producer who has read her file once does not have to learn a
   second row for a report or a fifth agreement. `.clockbanner` (section 4d)
   carries the arithmetic itself on both screens: script clearance worked
   backward from October 3 on the reports screen, and the opinion worked
   backward from the same date on the attorney screen, so the two hardest
   dates in Delivered read as the same kind of fact wherever she meets them.
   `.failblock` (section 4d) closes each screen with what happens if the
   report or the attorney comes back with something outstanding. What is
   new here is only the tight rhythm a plain heading-and-paragraph section
   needs once it is not a `.filegroup` or a `.clockbanner`, and the row that
   holds this screen's one primary action next to its one secondary link. */

.reportsec > * + * { margin-top: var(--space-2); }
.reportsec h2 + p { margin-top: 4px; }

.reportact { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

/* The one new row shape: a document already in the file, sitting inside the
   attorney's manifest, followed by the plain sentence that closes the
   section. `.filerow` never anticipated a paragraph after its own list, so
   the gap between them is set here rather than forced into a shared rule
   nothing else needs. */
.filegroup .filerows + p { margin-top: var(--space-2); }
/* == end reports == */

/* == binder == */
/* Screen 31, the delivery binder (D12). One list, the distributor's own
   fourteen items in the distributor's own order, never regrouped by
   state the way delivery.html groups the same fourteen. Composes
   .filegroup / .filerow (base) and .emptystate / .failblock (== states ==)
   unchanged. The only new mark is the index number in front of each row,
   because keeping the distributor's own order is the whole point of the
   screen. */
.binderrow-num { flex: none; width: 22px; padding-top: 2px; font-size: var(--text-13); color: var(--ink-2); }
/* Layout only; pair the mark with the shared .mono utility in the markup
   for the font itself, same as .filegroup-count does elsewhere. */
/* == end binder == */

/* == another == */
/* Screen 32: the way-in shell reused verbatim from intake-number.html (no
   sidebar, D-050), collapsed to one screen instead of a wizard, since M7's
   whole promise is that starting again takes two minutes rather than eleven
   questions. The four carried-over answers reuse .taskrow for the three that
   still hold and .failblock for the one that doesn't, so the same shapes
   that mean "settled" and "not settled" everywhere else in the product mean
   the same thing here. The four new answers reuse .field, .iq-count and
   .seg verbatim from == intake ==, and the number below reuses .lines and
   .total verbatim from == intake-number ==, so all three screens read as
   the same product asking the same kind of question. The only new rule is
   the gap between the carried-over list and the one that's out of date. */
.carrylist > * + * { margin-top: var(--space-2); }
/* == end another == */

/* == rescue == */
/* Screen 33. The one new shape this screen needs: a short list of what
   Mula can still do quickly, each line marked with the same mint check
   a done task carries elsewhere, because "can do this" and "done" are
   close enough in spirit to share a mark. */
.rescue-can { list-style: none; margin: var(--space-2) 0 0; padding: 0; display: grid; gap: var(--space-2); }
.rescue-can li { display: flex; align-items: flex-start; gap: var(--space-2); font-size: var(--text-15); color: var(--ink); }
.rescue-can svg { width: 16px; height: 16px; flex: none; margin-top: 3px; color: var(--mint); }
/* == end rescue == */

/* == billing == */
/* Billing reuses the shared .total and the .filerow grammar rather than
   inventing a table: a row is a name, a mono dollar figure, and a state,
   the same three facts every other list in this product already shows.
   The corrected certificate keeps the exact same three columns as the
   paid lines above it, so the $0.00 reads in the same column as $6,840
   instead of sitting in a separate callout: the guarantee is the
   arithmetic itself, not a badge next to it. Its state gets the one
   pill-status on the page, mint and checked, because it is the single
   fact this screen most needs a producer to see. */
.billcol { max-width: 640px; }
.billcol > * + * { margin-top: var(--space-4); }

.billrows { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.billrow { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: var(--space-3); align-items: baseline; padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.billrows li:first-child .billrow { border-top: 0; padding-top: 0; }
.billrow-name { display: block; font-size: var(--text-15); font-weight: 500; color: var(--ink); }
.billrow-name small { display: block; margin-top: 2px; font-weight: 400; font-size: var(--text-13); color: var(--ink-2); max-width: 48ch; }
.billrow-amt { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink); justify-self: end; }
.billrow-state { font-size: var(--text-13); color: var(--ink-2); white-space: nowrap; justify-self: end; }
.billrow-state .pill-status { justify-self: end; }

@media (max-width: 620px) {
  .billrow { grid-template-columns: 1fr; gap: 4px; }
  .billrow-amt, .billrow-state { justify-self: start; }
}
/* == end billing == */

/* == notifications == */
/* Composes .notifrow, .failblock, .crumb and base type from section 4d and
   earlier sections. .notifgroup is the only new rule: a plain grid wrapper
   that gives each dated group (the clock pair, today, the older pair, the
   standing row) a line-length cap and one gap between its heading and its
   list of rows. It does not touch .notifrow itself. */
.notifgroup { display: grid; gap: var(--space-2); max-width: 720px; }
/* == end notifications == */

/* == states == */
/* empty.html and failure.html are states sheets in system.html's own shape: sheet
   furniture (.sheet, .demo, .note) lives inline on each page, exactly as it does on
   system.html itself, since it is page furniture, not shared product chrome. Nothing
   here redefines .emptystate, .failblock, .notifrow, .clockbanner or .notice; both
   sheets compose them unchanged from section 4d, so this block stays empty on purpose. */
/* == end states == */
