/* The Actions tool — /actions.
   Ported from the 3.0 kit's Tools.dc.html, whose Actions screen begins at line 106.

   Loaded via yield :page_stylesheets, not on every page — a ranked action list has
   nothing to say to any other surface.

   Everything here resolves through --zw-* tokens. Green appears in exactly two places,
   both of them measurement: the impact/effort dots and the done state a row wears (its
   tint and trailing check — plus the personal list's tick boxes, which are the same
   statement). Every CTA is the action blue. That split is 3.0's colour law and
   green_is_never_a_button_test.rb enforces the button half of it. */

/* Matches the site header rather than the kit's 1440px tool measure, for the reason
   calendar_tool.css records: a tool surface wider than the menu above it reads as a
   broken page rather than a wide one. Mirrored as values so the two can be compared. */
.zw-act-page {
  width: 100%;
  max-width: 80rem; /* Tailwind max-w-7xl, the site header's measure */
  margin: 0 auto;
  padding: 28px 1rem 56px; /* px-4 */
}

@media (min-width: 640px) {
  .zw-act-page { padding-inline: 1.5rem; } /* sm:px-6 */
}

@media (min-width: 1024px) {
  .zw-act-page { padding-block: 44px 72px; padding-inline: 2rem; } /* lg:px-8 */
}

/* --- masthead -------------------------------------------------------------- */

.zw-act-title {
  font-family: var(--zw-font-serif);
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--zw-ink);
  margin: 0 0 6px;
}

.zw-act-dek {
  margin: 0 0 26px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--zw-muted);
  max-width: 620px;
}

/* --- shell ----------------------------------------------------------------- */

.zw-act-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

@media (min-width: 1024px) {
  .zw-act-shell { grid-template-columns: minmax(0, 1fr) 320px; gap: 44px; }
}

/* A grid child defaults to min-width:auto, so one long unbroken word — a pasted URL in an
   action's summary — can push the column wider than its track and shove the sidebar off. */
.zw-act-main { min-width: 0; }

/* --- band headers ---------------------------------------------------------- */

.zw-act-band {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 8px 2px;
}

/* The kit separates bands with a 34px gap below the LIST, not above the header, so a
   band's label sits tight to its own items rather than floating between two groups. */
.zw-act-list { margin-bottom: 34px; }

/* "Yours" is the one label that sits INSIDE a list rather than above one, so nothing below
   it supplies the gap other band labels inherit — it needs its own, or it collides with the
   shared action directly above. Less than a band gap, because it subdivides a band rather
   than starting one. */
.zw-act-list > .zw-act-band { margin-top: 18px; }

/* Except for a list nested in a list: the Yours list renders inside the Single Actions one,
   which already carries the band gap. Its own would push the cap toggle away from the rows
   the toggle belongs to. */
.zw-act-list--tight { margin-bottom: 0; }

.zw-act-band__label {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--zw-pin-slate);
  white-space: nowrap;
}

.zw-act-band__rule {
  flex: 1;
  height: 1px;
  background: var(--zw-border-warm);
}

.zw-act-band__meta {
  font-size: 13px;
  color: var(--zw-muted);
  white-space: nowrap;
}

/* --- single actions -------------------------------------------------------- */

.zw-act-list { display: grid; gap: 1px; }

/* A Single Action is a ROW, not a card, until you open it.
   Kit values (Tools.dc.html:2246-2250, computed per item):
     closed  background transparent · border transparent · no shadow · padding 11px 18px
     open    background #faf8f4     · border #ece9e3     · lift shadow · padding 16px 18px · margin 6px 0
     hover   background #faf8f4
   Shipping these as permanently white bordered cards was the "doesn't look like the mock
   up" defect: four boxed cards where the kit has a flush chromeless list that lifts only
   the item under discussion.

   `#faf8f4` resolves to --zw-surface-warm (#fbfaf7), whose declared role is exactly "row
   hover, quiet fills" — one point per channel apart and imperceptible, which is preferable
   to a second near-identical token. The open shadow uses --zw-shadow-float (10px 28px)
   against the kit's 8px 26px, for the same reason. */
.zw-act-item {
  padding: 11px 18px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--zw-radius-md);
  transition: background var(--dur-3) var(--zw-ease-out),
              box-shadow var(--dur-3) var(--zw-ease-out),
              border-color var(--dur-3) var(--zw-ease-out);
}

.zw-act-item:hover { background: var(--zw-surface-warm); }

/* :has() rather than a class toggled in JS — the <details> already holds the open state,
   and duplicating it into a class gives two sources of truth that can disagree. */
.zw-act-item:has(details[open]) {
  margin: 6px 0;
  padding: 16px 18px;
  background: var(--zw-surface-warm);
  border-color: var(--zw-border-warm);
  box-shadow: var(--zw-shadow-float);
}

.zw-act-item__row { display: flex; align-items: flex-start; gap: 13px; }

.zw-act-check__form { margin: 0; flex: none; }

/* Green, and correctly so: a completed action is a measurement, not an invitation. */
.zw-act-check {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 1px;
  padding: 0;
  font-size: 11px;
  line-height: 1;
  color: transparent;
  background: transparent;
  /* The kit's #d5d0c7, not one of the structural hairlines. An unchecked box outlined in
     --zw-border-warm (#ece9e3, 1.21:1 on white) is nearly invisible — reported as "way
     lower contrast than in the spec", and correctly. */
  border: 1.5px solid var(--zw-border-warm-strong);
  /* 5px, from the kit. A tick box is square; rounding it to a circle turns a checkbox
     into a radio button, which says "pick one of these" rather than "tick what you did". */
  border-radius: 5px;
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out), border-color var(--dur-2) var(--zw-ease-out);
}

.zw-act-check:hover { border-color: var(--zw-ladder-1); }

.zw-act-check--on {
  background: var(--zw-ladder-1);
  border-color: var(--zw-ladder-1);
  color: var(--zw-ladder-1-ink);
}

.zw-act-item__body { flex: 1; min-width: 0; }

.zw-act-item__summary {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  list-style: none;
}

.zw-act-item__summary::-webkit-details-marker { display: none; }

.zw-act-item__title {
  font-size: 15px;
  font-weight: 500;
  color: var(--zw-ink);
}

/* Done is lighter text, NOT a strikethrough.
   The kit strikes it through (`strike: isDone ? "line-through" : "none"`), and the owner
   overruled that: a struck line reads as cancelled or withdrawn, where a finished action is
   something you did. --zw-quiet is the kit's own done-text colour (#9a978f) — the recession
   carries the meaning on its own.
   The swap card's "from" keeps its strikethrough: there it means "stop buying this", which
   is a different statement from "you have done this". */
.zw-act-item__title--done { color: var(--zw-quiet); text-decoration: none; }

/* A personal row SWAPS for its editor rather than sitting above it, which is what the kit
   does (an edited row is filtered out of the list and the composer takes its place). Left
   stacked, the title appeared twice — once as the summary and once as the input's own
   placeholder. The shared list's rows keep their summary, because there the title is the
   heading for a description rather than a field you are editing. */
.zw-act-item--personal details[open] > .zw-act-item__summary { display: none; }

/* An unnamed to-do reads as a blank waiting to be filled, not as a thing called "New
   action": lighter weight and a recessive colour, as the kit has it (titleWeight 400,
   titleFg #b9b5ac). */
.zw-act-item__title--untitled { font-weight: 400; color: var(--zw-whisper); }

.zw-act-flag {
  display: inline-flex;
  align-items: center;
  align-self: center;
  gap: 5px;
  padding: 2px 8px 2px 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--zw-ladder-1);
  background: var(--zw-green-50);
  border-radius: var(--zw-radius-pill);
  white-space: nowrap;
}

.zw-act-flag__star { display: flex; }

.zw-act-item__detail { display: grid; gap: 8px; margin-top: 10px; }

.zw-act-item__dek,
.zw-act-item__fit,
.zw-act-item__scores {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--zw-muted);
}

.zw-act-item__fit { color: var(--zw-pin-slate); font-weight: 500; }

.zw-act-item__scores { display: flex; flex-wrap: wrap; gap: 18px; }

.zw-act-score {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--zw-faint);
}

/* --- rating dots ----------------------------------------------------------- */

.zw-act-dots { display: inline-flex; gap: 3px; }

.zw-act-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--zw-border-warm);
}

.zw-act-dot--on { background: var(--zw-ladder-1); }

/* --- ghost button ---------------------------------------------------------- */

.zw-act-ghost__form { margin: 0; }

/* button_to wraps the button in a form, so the auto-margin has to live on the wrapper —
   on the button it would only push within a form that is already only as wide as it is. */
.zw-act-ghost__form--skip { margin-left: auto; }

/* The kit's row of secondary actions: filled warm pills with NO border, not outlined
   rectangles. Bordered rects read as a form; these read as a row of quiet offers. */
.zw-act-ghost {
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-ink-2, var(--zw-muted));
  background: var(--zw-panel);
  border: none;
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-2) var(--zw-ease-out), color var(--dur-2) var(--zw-ease-out);
}

.zw-act-ghost:hover { background: var(--zw-border-warm-grid); color: var(--zw-ink); }

.zw-act-item__actions { display: flex; align-items: center; gap: 8px; }

/* "Not for me" sits at the far right of the row and is quieter than the offers beside it:
   the kit gives it margin-left:auto and no fill (Tools.dc.html:171). Turning something down
   should not compete with the two buttons inviting you to do it. */
.zw-act-ghost--skip {
  margin-left: auto;
  padding: 6px 10px;
  background: none;
}

.zw-act-ghost--skip:hover { background: var(--zw-border-warm-grid); color: var(--zw-ink); }

/* --- the one CTA style: blue, because it acts ------------------------------ */

.zw-act-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-surface);
  background: var(--zw-blue-700);
  border: none;
  border-radius: var(--zw-radius-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-cta:hover { background: var(--zw-blue-800); color: var(--zw-surface); }

/* The overflow link under a capped band. Quiet, aligned with the row titles above it rather
   than the card edge, so it reads as the end of the list instead of a control beside it. */
.zw-act-more {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-blue-700);
}

.zw-act-more:hover { color: var(--zw-blue-800); }

/* --- swaps ----------------------------------------------------------------- */

.zw-act-swap {
  display: block;
  padding: 16px 18px;
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-md);
  background: var(--zw-surface);
  box-shadow: var(--zw-shadow-sm);
  transition: box-shadow var(--dur-2) var(--zw-ease-out), border-color var(--dur-2) var(--zw-ease-out);
}

.zw-act-swap:hover { box-shadow: var(--zw-shadow-md); border-color: var(--zw-border-warm); }
.zw-act-swap:hover .zw-act-swap__to,
.zw-act-swap:hover .zw-act-swap__title { color: var(--zw-blue-700); }

.zw-act-swap__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* The children are spans inside an anchor now, so the ones that were <p> need their own
   block behaviour back. */
.zw-act-swap__dek,
.zw-act-swap__meta { display: block; }

.zw-act-swap__title { font-size: 15px; font-weight: 600; color: var(--zw-ink); }

/* The pair is the heading when we have one, so it carries the heading's weight rather
   than sitting under a title that repeated it. */
.zw-act-swap__pair {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  font-size: 15px;
}

.zw-act-swap__from { color: var(--zw-faint); text-decoration: line-through; }
.zw-act-swap__arrow { color: var(--zw-quiet); }
.zw-act-swap__to { color: var(--zw-ink); font-weight: 600; }

.zw-act-swap__dek { margin: 8px 0 0; font-size: 14px; line-height: 1.55; color: var(--zw-muted); }

.zw-act-swap__meta {
  display: inline-block;
  margin-top: 8px;
  font-size: 12px;
  color: var(--zw-faint);
}

/* --- petitions ------------------------------------------------------------- */

.zw-act-petition {
  padding: 18px 20px;
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-md);
  background: var(--zw-surface);
  box-shadow: var(--zw-shadow-sm);
}

.zw-act-petition__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.zw-act-petition__title { font-size: 15px; font-weight: 600; color: var(--zw-ink); }
.zw-act-petition__title:hover { color: var(--zw-blue-700); }

.zw-act-petition__scope {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: var(--zw-faint);
}

.zw-act-petition__bar { margin-bottom: 8px; }

.zw-act-petition__count { margin: 0; font-size: 13px; color: var(--zw-muted); }
.zw-act-petition__count strong { color: var(--zw-ink); }

.zw-act-petition__dek { margin: 8px 0 0; font-size: 14px; line-height: 1.55; color: var(--zw-muted); }

/* --- masthead: title + the setup as a sentence ------------------------------ */

.zw-act-masthead { margin-bottom: 26px; }

.zw-act-sentence {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  margin: 8px 0 0;
  font-size: 16px;
  color: var(--zw-muted);
}

/* The two editable words. Dashed underline so they read as answerable, not as fields —
   the sentence should look like prose that happens to be adjustable. */
.zw-act-sentence__word {
  appearance: none;
  -webkit-appearance: none;
  /* A select sizes to its WIDEST option, which ran the underline 200px past "student" and
     broke the sentence into two halves. field-sizing shrinks it to the chosen value; where it
     is unsupported the max-width keeps the overrun to something a sentence survives. */
  field-sizing: content;
  max-width: 13ch;
  padding: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--zw-ink);
  background: none;
  border: none;
  border-bottom: 1px dashed var(--zw-border-warm-strong);
  border-radius: 0;
  cursor: pointer;
}

.zw-act-sentence__word:hover { border-bottom-color: var(--zw-ink); }
.zw-act-sentence__word:focus { outline: none; border-bottom-style: solid; border-bottom-color: var(--zw-blue-700); }

/* One editable word: the native select, with a styled menu layered over it on wide screens.
   The select is always the field — it just becomes invisible once the menu is doing the
   showing, so there is still exactly one control and one value. */
.zw-act-choice { position: relative; display: inline-flex; }

.zw-act-choice__menu-wrap { display: none; }

/* Enhanced (desktop): the menu shows and the select goes transparent ON TOP of it, so a click
   still lands on the real control for anything relying on it, while the menu is what you see.
   Not `display: none` on the select — a hidden field is skipped by some autofill and by
   Capybara's default visibility, and it is still the thing that submits. */
.zw-act-choice--enhanced .zw-act-choice__menu-wrap { display: inline-flex; }

.zw-act-choice--enhanced .zw-act-choice__native {
  position: absolute;
  inset: 0;
  width: 100%;
  opacity: 0;
  pointer-events: none;
}

.zw-act-choice__label {
  padding: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--zw-ink);
  background: none;
  border: none;
  border-bottom: 1px dashed var(--zw-border-warm-strong);
  cursor: pointer;
  white-space: nowrap;
}

.zw-act-choice__label:hover { border-bottom-color: var(--zw-ink); }

/* The part a native select cannot give us. */
.zw-act-choice__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  display: grid;
  min-width: 190px;
  padding: 6px;
  background: var(--zw-surface);
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-md);
  box-shadow: var(--zw-shadow-float);
}

.zw-act-choice__option {
  padding: 7px 10px;
  font-size: 14px;
  text-align: left;
  white-space: nowrap;
  color: var(--zw-ink);
  background: none;
  border: none;
  border-radius: var(--zw-radius-sm);
  cursor: pointer;
}

.zw-act-choice__option:hover { background: var(--zw-surface-warm); }

.zw-act-choice__option--on { font-weight: 600; color: var(--zw-blue-700); }

/* --- the two-column shell -------------------------------------------------- */

.zw-act-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 28px;
  align-items: start;
}

@media (min-width: 1024px) {
  .zw-act-grid { grid-template-columns: minmax(0, 1fr) 360px; gap: 44px; }
  /* Clear of the sticky site header, not tucked under it. --zw-header-h is that header's
     height; the extra 24px is the breathing room the owner asked for. */
  .zw-act-detail { position: sticky; top: calc(var(--zw-header-h) + 24px); }
}

/* --- a row, whatever its kind ---------------------------------------------- */

.zw-act-row {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 18px;
  border: 1px solid transparent;
  border-radius: var(--zw-radius-md);
  transition: background var(--dur-2) var(--zw-ease-out), border-color var(--dur-2) var(--zw-ease-out);
}

.zw-act-row:hover { background: var(--zw-surface-warm); }

/* Selected reads as the row the panel is describing — a quiet tie between the two columns,
   not a second emphasis competing with the panel itself. */
.zw-act-row--selected { background: var(--zw-surface-warm); border-color: var(--zw-border-warm); }

/* Done is a state the row WEARS, not a control it offers: the leading tick box went with
   the first feedback round (Lydia, 2026-08-18 — a box beside a row you also click to read
   is two controls asking one question). Green tint plus trailing check, and correctly
   green: a completed action is a measurement, not an invitation. After the hover and
   selected rules, because done must win both fights — a finished row does not un-green
   while you look at it. */
.zw-act-row--done,
.zw-act-row--done:hover,
.zw-act-row--done.zw-act-row--selected { background: var(--zw-green-50); }

.zw-act-row__check { display: flex; flex: none; color: var(--zw-ladder-1); }

/* Rows past a band's cap: rendered, hidden, revealed by the toggle without a request. */
.zw-act-row--hidden { display: none; }
.zw-act-row--revealed { display: flex; }

.zw-act-row__body {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 0;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
}

.zw-act-row__title { font-size: 15px; font-weight: 500; color: var(--zw-ink); }

.zw-act-row--done .zw-act-row__title { color: var(--zw-quiet); }

.zw-act-row__status { font-size: 13px; color: var(--zw-faint); white-space: nowrap; }

/* --- the detail panel ------------------------------------------------------ */

.zw-act-detail {
  padding: 18px 20px;
  background: var(--zw-surface);
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-md);
  box-shadow: var(--zw-shadow-hairline);
}

.zw-act-detail__head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }

.zw-act-detail__meta { font-size: 12px; color: var(--zw-faint); }

.zw-act-detail__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: auto;
  padding: 0;
  font-size: 13px;
  color: var(--zw-faint);
  background: none;
  border: none;
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
}

.zw-act-detail__close:hover { background: var(--zw-border-warm-grid); color: var(--zw-ink); }

.zw-act-detail__body { display: grid; gap: 12px; }

.zw-act-detail__title {
  margin: 0;
  font-family: var(--zw-font-serif);
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--zw-ink);
}

.zw-act-detail__dek,
.zw-act-detail__why,
.zw-act-detail__prompt,
.zw-act-detail__count { margin: 0; font-size: 14px; line-height: 1.55; color: var(--zw-muted); }

.zw-act-detail__count strong { color: var(--zw-ink); }
.zw-act-detail__fit { margin: 0; font-size: 14px; font-weight: 500; color: var(--zw-pin-slate); }

/* --- an action's rich description -------------------------------------------
   The panel used to show `body.to_plain_text` in a single `.zw-act-detail__dek`
   paragraph, so nothing an admin did in the editor — bold, a list, a wikilink —
   reached the reader. It now renders the document, which means this block can
   receive anything the editor emits. `action.body` is not sanitized (only the
   wiki page runs renderer output through `sanitize`), so every one of those
   blocks arrives verbatim and needs a rule here.

   Preflight has already zeroed margins and list styles and set
   `a { color: inherit; text-decoration: inherit }`, so "unstyled" here is not
   the browser default — it is paragraphs running together and links that look
   like prose.

   The paragraph deliberately matches `.zw-act-detail__dek` above: nearly every
   description is one paragraph, and anchoring to the rule it replaces is what
   keeps this change invisible for that case instead of restyling every action
   on the page. */
.zw-act-detail__prose {
  font-size: 14px;
  line-height: 1.55;
  color: var(--zw-muted);
}

.zw-act-detail__prose > :first-child { margin-top: 0; }
.zw-act-detail__prose > :last-child { margin-bottom: 0; }

.zw-act-detail__prose p { margin: 0 0 10px; font-size: 14px; line-height: 1.55; }

.zw-act-detail__prose strong { font-weight: 600; color: var(--zw-ink); }
.zw-act-detail__prose em { font-style: italic; }
.zw-act-detail__prose s { text-decoration: line-through; }
.zw-act-detail__prose u { text-decoration: underline; }

.zw-act-detail__prose ul,
.zw-act-detail__prose ol {
  margin: 0 0 10px;
  padding-left: 20px;
  list-style-position: outside;
}

.zw-act-detail__prose ul { list-style-type: disc; }
.zw-act-detail__prose ol { list-style-type: decimal; }
.zw-act-detail__prose li { margin: 0 0 4px; }
.zw-act-detail__prose li > p { margin: 0; }

/* Smaller than `.zw-act-detail__title` (22px), so a heading inside the
   description cannot compete with the action's own name. */
.zw-act-detail__prose h1,
.zw-act-detail__prose h2,
.zw-act-detail__prose h3,
.zw-act-detail__prose h4,
.zw-act-detail__prose h5,
.zw-act-detail__prose h6 {
  margin: 14px 0 6px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--zw-ink);
}

.zw-act-detail__prose a {
  color: var(--zw-blue-700);
  text-decoration: none;
  border-bottom: 1px solid var(--zw-blue-300);
}

.zw-act-detail__prose a:hover { border-bottom-color: var(--zw-blue-700); }

/* The panel is a narrow sidebar and an uploaded image carries its natural
   pixel width, so without the cap one image blows the column out. */
.zw-act-detail__prose img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 10px 0;
  border-radius: var(--zw-radius-sm);
}

.zw-act-detail__prose blockquote {
  margin: 10px 0;
  padding-left: 12px;
  border-left: 2px solid var(--zw-border-warm-grid);
  color: var(--zw-faint);
}

.zw-act-detail__prose code {
  padding: 1px 4px;
  font-size: 13px;
  background: var(--zw-border-warm-grid);
  border-radius: var(--zw-radius-xs);
}

.zw-act-detail__prose pre {
  margin: 10px 0;
  padding: 10px 12px;
  overflow-x: auto;
  background: var(--zw-border-warm-grid);
  border-radius: var(--zw-radius-sm);
}

.zw-act-detail__prose pre code { padding: 0; background: none; }

.zw-act-detail__prose hr {
  margin: 14px 0;
  border: 0;
  border-top: 1px solid var(--zw-border-warm-grid);
}

/* Stacked, so the replacement reads as the answer to the thing above it. */
.zw-act-detail__swap { display: grid; gap: 2px; margin: 0; font-size: 14px; }
.zw-act-detail__from { color: var(--zw-faint); text-decoration: line-through; }
.zw-act-detail__to { color: var(--zw-ink); font-weight: 600; }

.zw-act-detail__scores { display: flex; flex-wrap: wrap; gap: 18px; margin: 0; }
.zw-act-detail__links { display: flex; flex-wrap: wrap; gap: 8px; }

/* "Not for me" carries no pill. It sits beside the primary action and declining should not
   look like a second thing to do — the same call as the old --skip modifier. */
.zw-act-detail__foot .zw-act-ghost {
  padding: 6px 4px;
  background: none;
  color: var(--zw-faint);
}

.zw-act-detail__foot .zw-act-ghost:hover { background: none; color: var(--zw-ink); }

.zw-act-detail__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--zw-border-warm-inner);
}

.zw-act-detail__primary-form { margin: 0; flex: 1; }

/* Worn by a button when signed in and by the sign-in link when not, so it centres its own
   text — an <a> does not inherit a button's centring. */
.zw-act-detail__primary {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 9px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--zw-surface);
  background: var(--zw-blue-700);
  border: none;
  border-radius: var(--zw-radius-sm);
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-detail__primary:hover { background: var(--zw-blue-800); }

.zw-act-detail__empty { padding: 22px 4px; text-align: center; }
.zw-act-detail__empty-icon { display: inline-flex; color: var(--zw-whisper); }
.zw-act-detail__empty-title { margin-top: 10px; font-size: 15px; font-weight: 600; color: var(--zw-ink); }
.zw-act-detail__empty-dek { margin: 6px 0 0; font-size: 14px; line-height: 1.55; color: var(--zw-faint); }

/* The band toggle is a button now, not a link — it expands in place. */
.zw-act-showall {
  justify-self: start;
  /* Flush with the band label above it, not indented to the row text — it belongs to the band,
     not to the list of rows. */
  margin: 10px 0 0;
  padding: 6px 0;
  font-size: 14px;
  /* A button centres its text and, as a grid item, stretches the full column — which put the
     label in the middle of the list. Both have to be undone, not just one. */
  text-align: left;
  color: var(--zw-faint);
  background: none;
  border: none;
  cursor: pointer;
}

/* Text, not a pill. A filled rounded hover on a flush chromeless list read as a stray
   button floating under the rows — the label is a quiet control, so it darkens and
   underlines rather than growing a shape. */
.zw-act-showall:hover { color: var(--zw-ink); text-decoration: underline; }

/* --- Yours: the reader's own to-dos ---------------------------------------- */

/* Add-row and composer SWAP rather than stack, as the kit has it. The summary is hidden
   while the details is open so only one of the two is ever on screen. */
.zw-act-add__form { margin: 0; }

/* A button that creates the row, not a disclosure that reveals a form. */
.zw-act-add__row {
  width: 100%;
  background: none;
  border: none;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 18px;
  cursor: pointer;
  list-style: none;
  border-radius: var(--zw-radius-md);
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-add__row::-webkit-details-marker { display: none; }
.zw-act-add__row:hover { background: var(--zw-surface-warm); }

/* A dashed tick box, so the row reads as a blank waiting to be filled. Kit line 222. */
.zw-act-add__plus {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex: none;
  font-size: 14px;
  line-height: 1;
  color: var(--zw-faint);
  border: 1.5px dashed var(--zw-border-warm-strong);
  border-radius: 5px;
}

.zw-act-add__label { font-size: 16px; color: var(--zw-faint); }

/* The editor is the row's own content: the row itself is already the lifted card once open,
   so a second card floating inside it would be a card in a card. */
.zw-act-composer,
.zw-act-composer--edit {
  margin: 10px 0 0;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
}

.zw-act-composer__body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 13px;
  align-items: start;
}

/* Lines the inputs up with the rows above. Solid, not dashed: it stands in for a real tick
   box rather than for an empty one. */
.zw-act-composer__mark {
  width: 20px;
  height: 20px;
  flex: none;
  margin-top: 1px;
  border: 1.5px solid var(--zw-border-warm-strong);
  border-radius: 5px;
}

.zw-act-composer__fields { display: grid; gap: 7px; min-width: 0; }

/* Borderless and transparent — the kit gives these no underline at all. An input that looks
   like a field turns a quick note into filling in a form. */
.zw-act-composer__title,
.zw-act-composer__note {
  min-width: 0;
  width: 100%;
  padding: 0;
  background: transparent;
  border: none;
  outline: none;
}

.zw-act-composer__title {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--zw-ink);
}

.zw-act-composer__note { font-size: 14px; color: var(--zw-muted); }

.zw-act-composer__foot {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--zw-border-warm-inner);
}

.zw-act-composer__hint { font-size: 13px; color: var(--zw-faint); }

/* The kit has no save button — it commits on Enter. We keep one because a form that only
   submits on a keystroke is unusable on a phone, but it stays quiet. */
.zw-act-composer__save {
  margin-left: auto;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-blue-700);
  background: none;
  border: none;
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-composer__save:hover { background: var(--zw-border-warm-grid); }

.zw-act-composer__form { margin: 0; }
.zw-act-composer__delete-form { margin: 0; }

/* An icon button, not a "Delete" label: it sits beside a save action and should not read as
   the equal-weight second option. Kit line 212. */
.zw-act-composer__delete {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  color: var(--zw-whisper);
  background: none;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out), color var(--dur-2) var(--zw-ease-out);
}

.zw-act-composer__delete:hover { background: var(--zw-advocacy-track); color: var(--zw-advocacy); }

/* The note, shown on a collapsed row. */
.zw-act-item__note { display: block; margin-top: 2px; font-size: 14px; color: var(--zw-muted); }

/* --- the plan chip and This week --------------------------------------------
   A plan is a warm fact, not a nag: the chip is sand — ladder step 4, the one surviving
   warm accent — because it is neither a measurement (green) nor an invitation (blue).
   It is worn by rows, by the week card, and by the picker's own summary once set. */

.zw-act-plan-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--zw-sand-ink);
  background: var(--zw-sand-tint);
  border-radius: var(--zw-radius-pill);
  white-space: nowrap;
}

.zw-act-week { margin-bottom: 34px; }

/* The one place besides the masthead this page uses the serif: "This week" is a section
   headline, which is one of the three placements the kit allows Petrona. */
.zw-act-week__title {
  font-family: var(--zw-font-serif);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--zw-ink);
}

.zw-act-week__band { margin-bottom: 10px; }
.zw-act-week__band .zw-act-band__meta { margin-left: auto; }

.zw-act-week__sun { display: flex; color: var(--zw-tool-calendar); }

/* Boxed where the bands below are flush, because this is a different kind of list: the
   catalogue offers, this one holds promises. Same card grammar as the detail panel. */
.zw-act-week__card {
  padding: 6px;
  background: var(--zw-surface);
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-xl);
  box-shadow: var(--zw-shadow-card);
}

.zw-act-week__rule { height: 1px; margin: 0 12px; background: var(--zw-border-warm-inner); }

.zw-act-week__row {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  min-height: 46px;
  padding: 10px 14px;
  background: none;
  border: none;
  border-radius: var(--zw-radius-sm);
  text-align: left;
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-week__row:hover { background: var(--zw-surface-warm); }

.zw-act-week__row--done,
.zw-act-week__row--done:hover { background: var(--zw-green-50); }

.zw-act-week__name { flex: 1; min-width: 0; font-size: 15px; font-weight: 500; color: var(--zw-ink); }

.zw-act-week__row--done .zw-act-week__name { color: var(--zw-quiet); }

.zw-act-week__note { margin: 8px 0 0 4px; font-size: 13px; color: var(--zw-quiet); }

/* --- the When? picker --------------------------------------------------------
   A <details> popover: the summary is the control, the card floats above the panel's
   foot. Colour law: the CHOOSING is blue (selected option, selected day), today is a
   green fact, and the resulting plan is the sand chip above. */

.zw-act-when { position: relative; }

.zw-act-when__summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-ink-2, var(--zw-muted));
  background: var(--zw-panel);
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  white-space: nowrap;
  list-style: none;
  transition: background var(--dur-2) var(--zw-ease-out), color var(--dur-2) var(--zw-ease-out);
}

.zw-act-when__summary::-webkit-details-marker { display: none; }
.zw-act-when__summary:hover { background: var(--zw-border-warm-grid); color: var(--zw-ink); }

/* Once a day is named, the summary IS the chip — one control that both shows the plan
   and reopens the picker to move it. */
.zw-act-when__summary--set { color: var(--zw-sand-ink); background: var(--zw-sand-tint); }
.zw-act-when__summary--set:hover { background: var(--zw-sand-tint); color: var(--zw-sand-ink); filter: brightness(0.97); }

/* Opens DOWNWARD from the summary. The panel sits high on the page under a sticky
   header, so a card floated upward runs beneath that header where nothing can click
   it; below the foot there is always page to scroll. */
.zw-act-when__card {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 30;
  width: 300px;
  padding: 12px 12px 10px;
  background: var(--zw-surface);
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-xl);
  box-shadow: var(--zw-shadow-float);
}

/* On a phone the popover has no room to float, so it becomes the sheet: pinned to the
   bottom of the viewport, full width, scrolling inside itself if it must. */
@media (max-width: 639px) {
  .zw-act-when__card {
    position: fixed;
    inset: auto 10px 10px;
    bottom: 10px;
    width: auto;
    max-height: 80vh;
    overflow-y: auto;
    border-radius: 20px;
    box-shadow: var(--zw-shadow-lift);
  }
}

.zw-act-when__form { margin: 0; display: grid; }

.zw-act-when__options { display: grid; gap: 2px; }

.zw-act-when__option {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 44px;
  padding: 0 10px;
  background: none;
  border: none;
  border-radius: var(--zw-radius-sm);
  text-align: left;
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-when__option:hover { background: var(--zw-surface-warm); }
.zw-act-when__option--on,
.zw-act-when__option--on:hover { background: var(--zw-blue-50); }

.zw-act-when__label { font-size: 14px; font-weight: 500; color: var(--zw-ink); }
.zw-act-when__option--someday .zw-act-when__label { color: var(--zw-muted); }
.zw-act-when__hint { font-size: 13px; color: var(--zw-faint); }
.zw-act-when__tick { display: flex; margin-left: auto; color: var(--zw-blue-700); }
.zw-act-when__option .zw-act-when__hint:last-child { margin-left: auto; }

/* Each rhythm keeps its own muted stroke, like the map's pins: identity, not decoration. */
.zw-act-when__glyph { display: flex; flex: none; }
.zw-act-when__glyph--today { color: var(--zw-tool-calendar); }
.zw-act-when__glyph--evening { color: var(--zw-pin-slate); }
.zw-act-when__glyph--trash_night { color: var(--zw-moss); }
.zw-act-when__glyph--weekend { color: var(--zw-clay); }
.zw-act-when__glyph--someday { color: var(--zw-ladder-2); }

.zw-act-when__hr { height: 1px; margin: 10px 4px; background: var(--zw-border-warm-inner); }

.zw-act-when__month { padding: 0 6px 6px; font-size: 13px; font-weight: 600; color: var(--zw-ink-2); }

.zw-act-when__dows {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
  padding: 0 4px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--zw-whisper);
  text-align: center;
}

.zw-act-when__grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
  padding: 2px 4px 0;
}

.zw-act-when__day {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 0;
  font-size: 13px;
  color: var(--zw-ink-2);
  background: none;
  border: none;
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-when__day:hover { background: var(--zw-surface-warm); }
.zw-act-when__day--past { color: var(--zw-whisper); cursor: default; }
.zw-act-when__day--next { color: var(--zw-faint); }
.zw-act-when__day--today { background: var(--zw-green-50); color: var(--zw-green-800); font-weight: 600; }
.zw-act-when__day--on,
.zw-act-when__day--on:hover { background: var(--zw-blue-700); color: var(--zw-surface); font-weight: 600; }

.zw-act-when__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  padding: 8px 6px 0;
  border-top: 1px solid var(--zw-border-warm-inner);
}

.zw-act-when__note { font-size: 12px; color: var(--zw-quiet); }

.zw-act-when__clear-form { margin: 0 0 0 auto; }

.zw-act-when__clear {
  padding: 4px 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-faint);
  background: none;
  border: none;
  border-radius: var(--zw-radius-pill);
  cursor: pointer;
}

.zw-act-when__clear:hover { color: var(--zw-ink); background: var(--zw-border-warm-grid); }

/* The stacked foot a task's panel uses: the big done button on its own line, then the
   picker and "Not for me" sharing the second. */
.zw-act-detail__foot--stacked { flex-direction: column; align-items: stretch; }
.zw-act-detail__foot-row { display: flex; align-items: center; gap: 8px; }

/* --- Habits ---------------------------------------------------------------- */

/* Boxed, unlike a Single Action row: a 21-day run with a progress track is something you
   commit to rather than a line you tick. Kit values, Tools.dc.html:278. */
.zw-act-habit {
  padding: 18px 20px;
  background: var(--zw-surface);
  border: 1px solid var(--zw-border-warm-2);
  border-radius: var(--zw-radius-md);
  box-shadow: var(--zw-shadow-hairline);
  transition: box-shadow var(--dur-3) var(--zw-ease-out), border-color var(--dur-3) var(--zw-ease-out);
}

.zw-act-habit:hover { box-shadow: var(--zw-shadow-dock); }

.zw-act-habit__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.zw-act-habit__lead { display: grid; gap: 4px; min-width: 0; }

.zw-act-habit__title { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; color: var(--zw-ink); }
.zw-act-habit__dek { font-size: 14px; line-height: 1.5; color: var(--zw-muted); }

/* Blue, not the kit's green. Starting a habit is an action, and 3.0's own law says green
   measures — the track below this is where the green belongs. */
.zw-act-habit__join {
  flex: none;
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--zw-surface);
  background: var(--zw-blue-700);
  border: 1px solid var(--zw-blue-700);
  border-radius: var(--zw-radius-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-2) var(--zw-ease-out);
}

.zw-act-habit__join:hover { background: var(--zw-blue-800); color: var(--zw-surface); }

/* Enrolled is a state, not an invitation, so it stops looking like a button to press. */
.zw-act-habit__join--on {
  color: var(--zw-ladder-1);
  background: var(--zw-green-50);
  border-color: var(--zw-green-50);
}

.zw-act-habit__join--on:hover { background: var(--zw-green-50); color: var(--zw-ladder-1); }

.zw-act-habit__track { margin-top: 14px; }

.zw-act-habit__foot { margin-top: 10px; }

.zw-act-habit__cadence { font-size: 13px; color: var(--zw-faint); }

.zw-act-habit__whylink {
  margin-top: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--zw-blue-700);
  cursor: pointer;
  list-style: none;
}

.zw-act-habit__whylink::-webkit-details-marker { display: none; }
.zw-act-habit__whylink:hover { color: var(--zw-blue-800); }

.zw-act-habit__whybody {
  margin-top: 12px;
  padding: 12px 14px;
  background: var(--zw-surface-warm);
  border-radius: var(--zw-radius-sm);
}

.zw-act-habit__whybody p { margin: 0 0 8px; font-size: 14px; line-height: 1.55; color: var(--zw-muted); }
.zw-act-habit__whybody p:last-child { margin-bottom: 0; }
