/* FABLS — only what castomo-dashkit does not already draw.
   Everything else — the shell, cards, lists, forms, badges, tables, meters,
   dialogs, the assistant and the drawings — is the kit's (public/dashkit),
   in FABLS's theme: the green ramp and the Hipster art fabls.io is built from.
   Every value here is a kit token; no colour is named in this file. */

/* ---------- Sign in ---------- */
.auth-title { font-size: var(--t3); }
/* The welcome words and the sign-in button are two separate beats: a clear pause between them. */
.auth-card > .stack-sm + * { margin-top: var(--s3); }
.auth-foot { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s0); }

/* ---------- Page furniture ---------- */
/* The page's rhythm. A screen puts its blocks straight into #view (a kit
   `.page`, plain block flow), so the space between two blocks is whatever
   margins they happen to carry — and two that carry none touch (the samples
   sat flush on "Generate a campaign with AI"). One rule spaces them all
   instead: every block stands one gap below the one before it. Vertical
   margins collapse in block flow, so a block that asks for more (the page
   head's, a kit `.section`) still gets exactly what it asked for, never the
   sum. */
#view > * + * { margin-top: var(--gap); }
#view > * + .section { margin-top: var(--s5); }
/* A section of tiles is set off by more than the gap between its own tiles,
   on both sides, or the block after it reads as one more tile. */
#view > * + .tile-section, #view > .tile-section + * { margin-top: var(--s4); }
.page-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s0) var(--s1); color: var(--ink-3); }
.muted { color: var(--ink-3); font-weight: 500; }
.text-warn { color: var(--warn); }
.card-legend { float: left; width: 100%; margin-bottom: var(--s0); font-size: var(--t2); }
.card-legend + * { clear: both; }
.form-group { display: grid; gap: var(--s2); padding-top: var(--s2); border-top: var(--rule-w) solid var(--rule); }
.form-group > legend { float: left; width: 100%; margin-bottom: var(--s0); }
.form-group > legend + * { clear: both; }
.form-actions { position: sticky; bottom: var(--s2); z-index: 2; padding: var(--s1); border-radius: var(--radius-card); background: color-mix(in oklab, var(--paper) 86%, transparent); backdrop-filter: blur(8px); width: fit-content; }
.bullets { display: grid; gap: var(--s-1); padding-inline-start: var(--s3); color: var(--ink-2); }
.noscript { padding: var(--s4); text-align: center; }
.settings-stack { max-width: 880px; }
/* A page's tabs (page-tabs.js) inside a grid — Reports draws them in its
   `.stack` body — would otherwise be as wide as the whole tab row, which never
   wraps: on a phone that pushed the page 160px past the screen. At zero the
   row scrolls inside itself instead, as the kit's `.tabs` means it to. */
.page-tabs { min-width: 0; }

/* The Home aside and every empty state draw from the kit; this only spaces the Home one. */
.home-art { padding-block: var(--s3); }
/* Home's inbox card is a head and nothing under it: no gap left for a body it does not have. */
.home-inbox > .card-head { margin-bottom: 0; }
/* A step's one action names the step in full ("Learn it from your website"),
   longer than a phone leaves a step room for: there it wraps inside its
   button rather than pushing the page sideways (§0.14). */
@media (max-width: 640px) {
  .steps .btn { max-width: 100%; white-space: normal; text-align: start; padding-block: 8px; }
}

/* ---------- Lists with actions ---------- */
.list > li { flex-wrap: wrap; }
.list > li > .btn-row { flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 640px) {
  .list > li > .btn-row { flex-basis: 100%; justify-content: flex-start; padding-inline-start: 0; }
}
.writer-prompt:empty { display: none; }
.writer-prompt { margin-top: var(--s0); }

/* ---------- Writers: the library pickers ----------
   The kit has the radio (`.check`) and the grid but no choosable card, so a
   persona option is a `.check` given a card's edge, marked when chosen. */
.pick { padding: var(--s1) var(--s2); border: var(--rule-w) solid var(--rule); border-radius: var(--radius-control); background: var(--paper-2); }
.pick:has(input:checked) { border-color: var(--accent-ink); background: var(--accent-wash); }
.pick small, .skill-list .check small { display: block; color: var(--ink-3); font-size: var(--t-1); }
/* The option count is the library's, so an odd last card spans the row rather than leaving a hole (§0.13). */
.pick-grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }
.skill-list > li { align-items: flex-start; }
/* The excerpt lines up with the skill's name, past the checkbox (18px box + the kit's 10px gap). */
.skill-excerpt { padding-inline-start: 28px; }

/* ---------- Disclosure and code ---------- */
.disclosure summary { width: fit-content; color: var(--accent-ink); font-size: var(--t-1); font-weight: 650; cursor: pointer; }
.disclosure[open] summary { margin-bottom: var(--s0); }
/* A connect card's "Step by step" (connect-guides.js): numbered, quiet, and as wide as the card's text. */
.connect-guide ol { margin: 0; padding-inline-start: 1.25em; display: grid; gap: 6px; max-width: var(--measure); color: var(--ink-2); font-size: var(--t-1); overflow-wrap: anywhere; }
.connect-guide .hint { margin: var(--s0) 0 0; }
.code-block {
  max-height: 22rem;
  overflow: auto;
  margin: 0;
  padding: var(--s2);
  border-radius: var(--radius-control);
  background: var(--field);
  color: var(--ink-2);
  font: 500 var(--t-1) / 1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ---------- Brand ---------- */
.brand-about { max-width: var(--measure); color: var(--ink-2); margin-bottom: var(--s2); }
.swatches { display: flex; flex-wrap: wrap; gap: var(--s0); }
.swatch { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-1); }
.swatch::before { content: ""; width: 18px; height: 18px; border-radius: 6px; background: var(--swatch); box-shadow: inset 0 0 0 var(--rule-w) var(--rule-strong); }
.kit-text { display: grid; gap: var(--s0); }
.kit-text-tools { justify-content: space-between; align-items: center; }
.kit-count[data-over="true"] { color: var(--bad); }
.kit-ai { display: grid; gap: var(--s0); }
.kit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); gap: var(--s2); align-items: start; margin-block-start: var(--s2); }
.kit-figure { display: grid; gap: var(--s0); margin: 0; justify-items: start; }
.kit-figure figcaption { display: grid; gap: 2px; }
.kit-picture { max-inline-size: 100%; block-size: auto; border-radius: var(--radius-sm); box-shadow: 0 0 0 var(--rule-w) var(--rule-strong); }
.kit-picture[data-circle="true"] { border-radius: 50%; }
.colour-row { display: flex; align-items: center; gap: var(--s1); }
.colour-picker { inline-size: 44px; block-size: 36px; padding: 2px; border: 0; border-radius: var(--radius-sm); background: var(--paper-2); box-shadow: inset 0 0 0 var(--rule-w) var(--rule-strong); cursor: pointer; }
.colour-code { min-inline-size: 7ch; }
.brand-logos { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-block: var(--s2); }
.brand-logos img { max-height: 48px; max-width: 160px; padding: 6px; border-radius: var(--radius-sm); background: var(--paper-2); box-shadow: inset 0 0 0 var(--rule-w) var(--rule); }

/* ---------- Campaigns ---------- */
/* House rule: links are underlined. Same short, spring-stretching line as the
   kit's `.link` (dashkit.css §0.11), but in ink rather than accent so a report
   full of post titles stays calm; the line is drawn in currentColor. */
.row-link {
  color: var(--ink);
  font-weight: 650;
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / max(33%, 1.5em) 2px;
  padding-bottom: 2px;
  transition: background-size .6s var(--ease-spring);
}
.row-link:is(:hover, :focus-visible) { background-size: 100% 2px; }
:root[data-theme^="contrast"] .row-link { background-size: max(33%, 1.5em) 3px; }
@media (forced-colors: active) {
  .row-link { background: none; text-decoration: underline; }
}

/* ---------- Campaign tiles (js/campaign-tiles.js) ----------
   The brand's campaigns and the samples wear one tile. Its rows are shared
   with the tiles beside it through subgrid, so a two-line title or a longer
   goal moves that row down across the whole grid row and the split bars,
   the chips and the buttons stay level; the button always sits on the
   tile's foot. Without subgrid the tile is a column with its foot pushed
   down, which keeps the buttons level and lets the middle rows drift. */
.tile-section-title { flex: 1 1 14ch; min-width: 0; }
.tile-section-title h2 { font-size: var(--t2); }
.ctile-grid { align-items: stretch; }
.ctile {
  --tone: transparent;
  gap: var(--s1);
  padding: var(--s3) var(--s3) var(--s2);
  overflow: clip;
  cursor: pointer;
  transition: transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease);
}
@supports (grid-template-rows: subgrid) {
  .ctile { display: grid; grid-template-rows: subgrid; grid-row: span var(--rows); align-content: start; }
}
/* A status reads at a glance from the tile's top edge as well as its badge
   (never colour alone: the badge says it in words and shapes its dot). */
/* A phone keeps the words wide: the tile gives up padding before its text wraps again. */
@media (max-width: 560px) { .ctile { padding: var(--s2); } }
.ctile::before { content: ""; position: absolute; inset: 0 0 auto; height: 3px; background: var(--tone); }
.ctile[data-status="active"] { --tone: var(--ok); }
.ctile[data-status="paused"] { --tone: var(--warn); }
.ctile[data-status="planned"] { --tone: var(--accent-ink); }
/* A sample keeps the kit's dashed "not real" edge, flat until a pointer reaches it. */
.ctile.sample-region { box-shadow: none; background: var(--paper-2); }
@media (hover: hover) {
  .ctile:hover { box-shadow: var(--shadow-pop); }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .ctile:hover { transform: translateY(-2px); }
}
.ctile:has(.ctile-foot .btn:focus-visible) { box-shadow: 0 0 0 2px var(--focus), var(--shadow-pop); }

.ctile-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s1); min-width: 0; }
.ctile-icon { display: grid; place-items: center; width: 44px; height: 44px; flex: none; border-radius: var(--radius-control); background: var(--accent-soft); color: var(--accent-ink); }
.ctile-icon .ci { --ci-size: 22px; }
.ctile[data-kind="event"] .ctile-icon { background: color-mix(in oklab, var(--chart-4) 16%, transparent); color: color-mix(in oklab, var(--chart-4) 70%, var(--ink)); }
.ctile-badges { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px; min-width: 0; }
/* The name keeps two lines at most; the shared row gives a one-line name the
   same room a two-line neighbour takes, so both start the next row level. */
.ctile-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: var(--s0);
  font-size: var(--t1);
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.ctile-when { display: flex; flex-wrap: wrap; gap: 0 6px; margin-top: calc(var(--s0) * -1); color: var(--ink-3); font-size: var(--t-1); font-weight: 600; font-variant-numeric: tabular-nums; }
.ctile-dot { color: var(--rule-strong); }
.ctile-summary { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; color: var(--ink-2); overflow-wrap: anywhere; max-width: var(--measure); }

/* The channel split: one slim bar, a 2px gap between segments so two
   neighbours never merge, and the same numbers underneath as words. The
   colours are the theme's chart series, one per platform and the same
   everywhere, so a platform is recognised across tiles. */
.ctile-split { display: grid; gap: var(--s0); align-content: start; padding-top: var(--s0); }
.split-bar { display: flex; gap: 2px; height: 8px; }
.split-seg { flex: var(--share) 1 0; min-width: 6px; border-radius: 4px; background: var(--seg); }
.split-legend { display: flex; flex-wrap: wrap; gap: 2px var(--s2); margin: 0; padding: 0; list-style: none; color: var(--ink-2); font-size: var(--t-1); }
.split-legend li { display: inline-flex; align-items: center; gap: 6px; }
.split-legend li::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--seg); flex: none; }
.split-legend .num { color: var(--ink); font-weight: 700; }
.ctile-split [data-platform] { --seg: var(--ink-3); }
.ctile-split [data-platform="facebook"] { --seg: var(--chart-3); }
.ctile-split [data-platform="instagram"] { --seg: var(--chart-6); }
.ctile-split [data-platform="tiktok"] { --seg: var(--chart-5); }
.ctile-split [data-platform="wordpress"] { --seg: var(--chart-4); }
.ctile-split [data-platform="x"] { --seg: var(--chart-1); }
.ctile-split [data-platform="linkedin"] { --seg: var(--chart-2); }

.ctile-progress { align-content: start; gap: 6px; padding-top: 2px; }
.ctile-progress .meter-top { color: var(--ink-2); font-size: var(--t-1); }
.ctile-progress .meter-track { height: 6px; }
.ctile[data-status="paused"] .meter-fill { animation: none; }
.ctile-state { display: flex; align-items: center; gap: 6px; margin: 0; padding-top: 2px; color: var(--ink-2); font-size: var(--t-1); font-weight: 600; }
.ctile-state .ci { --ci-size: 16px; color: var(--ink-3); }

.ctile-chips { display: flex; flex-wrap: wrap; align-content: start; gap: 4px; margin: 0; min-width: 0; }
.ctile-foot { display: flex; justify-content: flex-end; margin-top: var(--s0); padding-top: var(--s1); border-top: var(--rule-w) solid var(--rule); align-self: end; }
/* Without subgrid each tile is a column: its name keeps two lines' room so
   the rows below start level, and the foot is pushed to the bottom edge. */
@supports not (grid-template-rows: subgrid) {
  .ctile-title { min-height: calc(2 * 1.3em); }
  .ctile-foot { margin-top: auto; }
}

.share-list > li { flex-wrap: nowrap; }
.share-field { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-3); }
.share-input { width: 5.5rem; text-align: end; }
.share-list .select { width: auto; min-width: 9rem; }
@media (max-width: 640px) {
  .share-list > li { flex-wrap: wrap; }
  .share-list .select { flex: 1; }
}

.calendar { display: grid; gap: var(--s3); }
.cal-date { position: sticky; top: calc(var(--bar-h) + var(--s0)); z-index: 1; width: fit-content; padding: 2px 10px; border-radius: var(--radius-pill); background: var(--accent-soft); color: var(--accent-ink); font-size: var(--t-1); font-weight: 700; }
/* A drafted slot has five actions: with the post's words at a basis of 0 the action row always "fit" beside them and
   squeezed the words to a few pixels (the row's buttons then sat on top of the channel's name). The words claim a
   readable width first, and the actions wrap under them when there is no room for both. */
.cal-slot { align-items: flex-start; flex-wrap: wrap; }
.cal-slot > .list-main { flex: 1 1 14rem; min-width: 0; }
.cal-time { flex: none; width: 3.4rem; padding-top: 2px; color: var(--ink-2); font-weight: 700; }
.cal-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
/* Under 420px two columns of facts, or a post squeezed beside its hour and icon, leave a word
   or two per line. One column reads: the fact under its label, the post under its hour.
   (grid-template-columns, not --cols: facts() sets --cols inline, which a media query can't beat.) */
@media (max-width: 419.98px) {
  .facts { grid-template-columns: minmax(0, 1fr); }
  .cal-slot { flex-wrap: wrap; align-items: center; }
  .cal-slot > .list-main { flex-basis: 100%; }
}
.cal-slot[data-state="skipped"] .list-main b,
.cal-slot[data-state="superseded"] .list-main b { color: var(--ink-3); text-decoration: line-through; text-decoration-thickness: 1px; }
.cal-edit { flex-basis: 100%; padding: var(--s2); border-radius: var(--radius-control); background: var(--accent-wash); }
/* One slot's conversation (views/campaigns.js commentThread): under the slot, full width. */
.cal-thread { flex-basis: 100%; padding: var(--s2); border-radius: var(--radius-control); background: var(--frame); }
.thread { display: grid; gap: var(--s1); margin: 0; padding: 0; list-style: none; }
.thread-item { display: flex; align-items: flex-start; gap: var(--s1); }
.thread-main { flex: 1; min-width: 0; }
.thread-meta { margin: 0; color: var(--ink-3); font-size: var(--t-1); }
.thread-meta b { color: var(--ink); }
.thread-body { margin: 2px 0 0; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.thread-empty { color: var(--ink-3); }
.thread-form { display: grid; gap: var(--s1); }
.thread-form .textarea { min-height: 0; }
.seats-line { display: flex; align-items: center; gap: 8px; margin: 0 0 var(--s2); color: var(--ink-2); }

/* ---------- "… with AI" cards ---------- */
/* The ask and its optional date share a row; the date keeps a date's width
   rather than a third of the card, and folds under the ask on a phone. */
.ai-ask { display: grid; grid-template-columns: minmax(0, 1fr) minmax(10rem, 14rem); gap: var(--s2); align-items: start; }
@media (max-width: 560px) { .ai-ask { grid-template-columns: minmax(0, 1fr); } }

/* ---------- Starter set and samples ---------- */
/* One card per ready-made writer or sample campaign: a head (face or icon,
   name, what it suits), a sentence, and its one action at the foot, so a row
   of cards lines its buttons up whatever the length of the words above. */
.starter-grid { align-items: stretch; }
.starter { display: flex; flex-direction: column; gap: var(--s1); padding: var(--s2); border: var(--rule-w) solid var(--rule); border-radius: var(--radius-card); background: var(--paper-2); min-width: 0; }
.starter > .btn-row { margin-top: auto; }
.starter-head { display: flex; align-items: center; gap: var(--s1); min-width: 0; }
.starter-head h3 { font-size: var(--t1); overflow-wrap: anywhere; }
.starter-head small { display: block; color: var(--ink-3); font-size: var(--t-1); }
.starter p { color: var(--ink-2); overflow-wrap: anywhere; }

/* ---------- Channels: the connect cards ----------
   Cards sit three to a row, the odd remainder in widened pairs (views/channels.js), so a row
   stretches them to one height: each card's words stay at its top and its
   buttons line up at its foot, whatever the length of the words above. */
.connect-grid > .form-card { display: flex; flex-direction: column; }
.connect-grid > .form-card > .btn-row:last-child { margin-top: auto; }
/* The widened pairs (an odd number of cards leaves two or four to pair up) get the
   same treatment: the wrapper stretches to the row and the card fills the wrapper,
   so the shorter of two (LinkedIn beside the taller X) is not left with a hole under it. */
.connect-split > .span-6 { display: flex; }
.connect-split > .span-6 > .form-card { flex: 1; display: flex; flex-direction: column; }
.connect-split > .span-6 > .form-card > .btn-row:last-child { margin-top: auto; }

/* ---------- Team ---------- */
/* The invitation link is shown once: the field and its copy button share a
   row, and the field takes whatever width is left without pushing the button
   off a phone. */
.copy-row { display: flex; gap: var(--s0); align-items: center; margin-top: var(--s0); }
.copy-row .input { flex: 1; min-width: 0; }
.role-list { list-style: none; display: grid; gap: var(--s1); }
.role-list li { display: grid; gap: 2px; }
.role-list span { color: var(--ink-2); }
.team-danger { margin-top: var(--s2); padding-top: var(--s2); border-top: var(--rule-w) solid var(--rule); }
.team-danger h3 { font-size: var(--t1); color: var(--bad); }

/* ---------- Tasks ---------- */
.task-list > li { align-items: flex-start; }
.task-check { padding-top: 2px; }
.task-list > li[data-state="done"] .list-main b { color: var(--ink-3); text-decoration: line-through; text-decoration-thickness: 1px; }
.task-who { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); }
/* No hole in the last row (ecosystem rule §0.13): a last card left alone in a
   three-column row takes the whole row, a pair shares it. */
@media (min-width: 861px) {
  :is(.starter-grid, .ctile-grid).cols-3 > :last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
  :is(.starter-grid, .ctile-grid).cols-3 > :last-child:nth-child(3n + 2) { grid-column: span 2; }
}
/* A sample's side cards keep their own height instead of stretching to the calendar's. */
.sample-region .split { align-items: start; }

/* ---------- Posts: the line under a slot, and the panel it opens ----------
   A calendar row carries one line of its post; the whole post opens under the
   row, full width, one at a time (post-panel.js), on the same quiet frame the
   slot's conversation uses, so a month of slots still reads as a calendar. */
.post-line { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--t-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
/* What a post is drafted from (the article chain) and the one message of its moment: two quiet lines under the post's own. */
.cal-source, .cal-message { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--t-1); }
.cal-source .badge { vertical-align: baseline; }
.cal-progress:empty { display: none; }
.cal-progress { flex-basis: 100%; }
.post-panel { flex-basis: 100%; padding: var(--s2); border-radius: var(--radius-control); background: var(--frame); border: var(--rule-w) solid var(--rule); }
/* An icon inside a sentence sits on its line at the sentence's size. */
.post-panel .hint .ci, .post-status .ci { --ci-size: 14px; vertical-align: -2px; }
.post-status { margin: 0; color: var(--ink-2); font-size: var(--t-1); }
.post-preview { display: grid; gap: var(--s1); padding: var(--s2); border-radius: var(--radius-control); background: var(--paper-2); box-shadow: inset 0 0 0 var(--rule-w) var(--rule); min-width: 0; }
.post-title { margin: 0; font-size: var(--t1); overflow-wrap: anywhere; }
.post-excerpt { margin: 0; color: var(--ink-2); overflow-wrap: anywhere; }
.post-text { margin: 0; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; max-width: var(--measure); }
.post-preview details .post-text { margin-top: var(--s0); max-height: 28rem; overflow: auto; }
.post-tags { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; }
.post-link { margin: 0; font-size: var(--t-1); overflow-wrap: anywhere; }
.post-said { margin-top: var(--s0); font-style: italic; overflow-wrap: anywhere; }
/* Pictures as a strip of squares: a carousel's ten fit a row on a desktop and wrap on a phone. */
.post-media { display: flex; flex-wrap: wrap; gap: var(--s0); margin: 0; padding: 0; list-style: none; }
.post-media:empty { display: none; }
.post-media li { display: grid; gap: 4px; justify-items: start; }
.post-media img, .post-video { display: block; width: 96px; height: 96px; border-radius: var(--radius-sm); object-fit: cover; background: var(--field); box-shadow: inset 0 0 0 var(--rule-w) var(--rule); }
.post-video { display: grid; place-content: center; justify-items: center; gap: 2px; color: var(--ink-2); font-size: var(--t-1); font-weight: 600; text-decoration: none; }
.post-edit { padding: var(--s2); border-radius: var(--radius-control); background: var(--paper-2); box-shadow: inset 0 0 0 var(--rule-w) var(--rule); }
.post-edit .form-group { padding-top: var(--s2); }
.post-count { margin-top: calc(var(--s0) * -1); text-align: end; }
.post-count [data-over="true"] { color: var(--bad); font-weight: 700; }
/* An X thread reads as the numbered posts it will be; a poll as its options. */
.post-thread { margin: 0; padding-inline-start: 1.4em; display: grid; gap: var(--s0); color: var(--ink); overflow-wrap: anywhere; }
.post-poll { display: grid; gap: 4px; margin: 0; }
.post-poll .bullets { margin: 0; }
.post-options { margin: 0; }
.post-thread-part { padding-inline-start: var(--s2); box-shadow: inset 2px 0 0 var(--rule); }
[dir="rtl"] .post-thread-part { box-shadow: inset -2px 0 0 var(--rule); }
/* An address, what it holds, and its button share a row; the address takes what is left. */
.media-address { display: flex; flex-wrap: wrap; gap: var(--s0); align-items: center; }
.media-address .input { flex: 1 1 14rem; min-width: 0; }
.media-address .select { flex: 0 0 auto; width: auto; }
/* Settings → Brand defaults: the browser lists ~420 zones, and a long one
   ("America/Argentina/ComodRivadavia") must not widen the form past its card. */
.zone-field { min-width: 0; justify-items: start; }
/* The searchable select shows one zone, not the longest of four hundred, so nothing sizes the
   field any more: it takes its column like the select beside it. Only the button stays at its words. */
.zone-field > .field { justify-self: stretch; }
.zone-field .select { width: 100%; max-width: 100%; }
.zone-field .btn { max-width: 100%; white-space: normal; text-align: start; }
/* Find a photo (public/js/photo-search.js): the search row wraps like the address row, and the
   results are square tiles the whole width of the editor, each one a button that copies it in. */
.photo-search { display: grid; gap: var(--s1); padding: var(--s2); border-radius: var(--radius-control); background: var(--frame); }
.photo-search[hidden] { display: none; }
.photo-bar { display: flex; flex-wrap: wrap; gap: var(--s0); align-items: center; }
.photo-bar .input { flex: 1 1 14rem; min-width: 0; }
.photo-bar .select { flex: 0 0 auto; width: auto; }
.photo-results { display: grid; gap: var(--s1); }
.photo-results:empty { display: none; }
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(104px, calc(33.3% - var(--s0))), 1fr)); gap: var(--s0); margin: 0; padding: 0; list-style: none; }
.photo-grid:empty { display: none; }
.photo-pick { position: relative; display: block; width: 100%; aspect-ratio: 1; padding: 0; border: 0; border-radius: var(--radius-sm); overflow: hidden; background: var(--field); cursor: pointer; }
/* Which source a search result comes from, small on its corner: a person comparing looks learns the libraries. */
.photo-source { position: absolute; inset-inline-start: 4px; inset-block-end: 4px; padding: 1px 6px; border-radius: var(--radius-pill); background: rgb(0 0 0 / .55); color: #fff; font-size: var(--t-2); font-weight: 600; text-transform: capitalize; pointer-events: none; }
.library-tabs { justify-self: start; max-width: 100%; }
/* Make a picture (public/js/picture-maker.js): the quality and shape choices are pills like the library's
   tabs; a crop's tick sits under its preview, and a preview never outgrows the card. */
.picture-maker .segmented { justify-self: start; max-width: 100%; }
.picture-crops .kit-picture { display: block; }
.picture-crops figcaption { justify-items: start; }
/* Make a video (public/js/video-maker.js): the shapes are pills like the picture maker's; the preview never outgrows the card or the screen. */
.video-maker .segmented { justify-self: start; max-width: 100%; }
.video-preview { display: block; max-width: 100%; max-height: min(28rem, 70vh); border-radius: var(--radius-control); background: #000; }
/* Pictures to draw from or start a video from (public/js/reference-picture.js): the added ones are the post's
   own thumbnails; "From this post" opens a shelf of the post's pictures, each a button with a plus on its corner. */
.reference-list:empty { display: none; }
.reference-shelf { display: flex; flex-wrap: wrap; gap: var(--s0); }
.reference-shelf[hidden] { display: none; }
.reference-pick { position: relative; display: block; padding: 0; border: 0; border-radius: var(--radius-sm); background: none; cursor: pointer; }
.reference-pick img { display: block; width: 72px; height: 72px; border-radius: var(--radius-sm); object-fit: cover; box-shadow: inset 0 0 0 var(--rule-w) var(--rule); }
.reference-pick [data-ci] { position: absolute; inset-block-end: 4px; inset-inline-end: 4px; padding: 2px; border-radius: var(--radius-pill); background: var(--paper); color: var(--ink); }
.reference-pick:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* The post's own video (Review and the editor) is a 9:16 reel: left alone it renders at its 720x1280 size, so the controls sat below the fold and the video looked unplayable. Same cap as .video-preview. */
.post-video-frame { display: block; max-width: 100%; max-height: min(28rem, 70vh); border-radius: var(--radius-control); background: #000; }
/* Shown only when this browser cannot play the file (video-playback.js); a reading line, not the video's width, and never wider than its column. */
.video-playback-note { margin: 0; max-width: min(100%, var(--measure, 36rem)); overflow-wrap: anywhere; }
/* My videos (public/js/video-library.js): a card is wider than a picture tile because it carries words (length, where it was used, whether it fits).
   The thumbnail is the video's first frame in its own shape, capped so a tall 9:16 clip never makes the row taller than the screen. */
.video-library-grid { grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); align-items: start; }
.video-card { display: grid; gap: var(--s0); min-width: 0; padding: var(--s1); border-radius: var(--radius-sm); background: var(--field); }
.video-thumb { position: relative; display: grid; place-items: center; border-radius: var(--radius-sm); overflow: hidden; background: #000; }
.video-thumb video { display: block; width: 100%; max-height: min(16rem, 40vh); object-fit: contain; }
.video-card .hint { overflow-wrap: anywhere; }
/* A video's name (public/js/video-name.js): the field over its Save and the "Saved" note, on a card and under the editor's video. */
.video-name { display: grid; gap: var(--s0); min-width: 0; }
.video-name .field { margin: 0; min-width: 0; }
.video-name input { width: 100%; min-width: 0; }
.video-name-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s0); }
.video-card-name { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.media-library > .btn { justify-self: center; }
.photo-pick img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur) var(--ease); }
.photo-pick:is(:hover, :focus-visible) img { transform: scale(1.04); }
.photo-pick:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.photo-pick[aria-busy="true"] { opacity: .55; cursor: progress; }
.draft-progress .meter-fill { animation: none; transition: width 1s linear; }
.draft-progress .hint { margin: 4px 0 0; }

/* The numbers a platform reported: a label and its figure, only the ones it sent. */
.metrics { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.metric { display: inline-flex; align-items: baseline; gap: 6px; padding: 2px 10px; border-radius: var(--radius-pill); background: var(--field); color: var(--ink-3); font-size: var(--t-1); }
.metric b { color: var(--ink); font-weight: 700; }
.metric-sum { background: var(--accent-soft); color: var(--accent-ink); }
.metric-sum b { color: var(--accent-ink); }

/* ---------- Publishing: the queue ---------- */
.queue-bar { display: flex; flex-wrap: wrap; gap: var(--s1); align-items: center; justify-content: space-between; }
.queue-head { margin: var(--s2) 0 var(--s0); }
.tab-count { min-width: 1.6em; padding: 0 6px; border-radius: var(--radius-pill); background: var(--paper); color: var(--ink-3); font-size: var(--t-2); font-weight: 700; line-height: 1.6; text-align: center; }
.queue-filters { display: flex; flex-wrap: wrap; gap: var(--s0); }
.queue-filters .select { width: auto; max-width: 16rem; }
.queue-filters .input { width: 12rem; max-width: 100%; }
.queue-list > li { align-items: flex-start; }
/* The kit's `.list-main { flex: 1 }` starts from zero width, so a row with six actions kept the
   buttons on its first line and squeezed the post (and its "Check before approving" note) into a
   column a word wide. Starting from 20rem, the post keeps a readable width and the actions wrap
   onto their own line beneath it instead (the row already wraps: `.list > li`). The note is the
   row's own last line (views/publishing.js), across the whole width from the post's left edge. */
.queue-list > li > .list-main { flex: 1 1 20rem; }
.queue-list > li > .queue-blocker { flex-basis: 100%; margin-top: 0; margin-inline-start: calc(6.6rem + var(--s1)); }
.queue-when { flex: none; display: grid; width: 6.6rem; padding-top: 2px; color: var(--ink-2); }
.queue-when small { color: var(--ink-3); font-size: var(--t-1); }
.queue-excerpt { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; font-weight: 600; }
.queue-channel { display: inline-flex; align-items: center; gap: 4px; }
.queue-channel .ci { --ci-size: 14px; color: var(--ink-3); }
/* What stops a post going out, on its row (views/publishing.js blockerOf): tinted like the kit's
   alerts so a queue of drafts shows at a glance which one will not go out as it is. */
.queue-blocker { --tone: var(--warn); display: flex; gap: var(--s1); align-items: flex-start; margin-top: var(--s1); padding: var(--s1) var(--s2); border-radius: var(--radius-control); background: color-mix(in oklab, var(--tone) 9%, var(--paper-2)); color: var(--ink); font-size: var(--t-1); }
.queue-blocker[data-tone="bad"] { --tone: var(--bad); }
.queue-blocker > .ci { --ci-size: 18px; flex: none; margin-top: 1px; color: var(--tone); }
.queue-blocker-body { display: grid; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
.queue-blocker-body p { margin: 0; color: var(--ink-2); }
.queue-blocker-body .bullets { margin: 0; }
.queue-blocker-sub { font-weight: 600; }
@media (max-width: 640px) {
  /* Four views in two rows of two, never a pill that wraps into a blob. */
  .queue-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; border-radius: var(--radius-control); }
  .queue-tabs label { display: grid; }
  .queue-tabs span { justify-content: center; padding: 4px 8px; white-space: normal; text-align: center; border-radius: calc(var(--radius-control) - 3px); }
  /* Two by two (four in a row squeezed the names to a word per line): icon, name, then the
     count at the far end, so every tile reads the same way from its start edge. */
  .publishing-tabs span { justify-content: flex-start; gap: 8px; min-height: 52px; padding: 6px 10px; text-align: start; }
  .publishing-tabs span .ci { --ci-size: 20px; flex: none; }
  .publishing-tabs .tab-label { flex: 1; min-width: 0; font-weight: 600; line-height: 1.2; }
  .publishing-tabs .tab-count { flex: none; }
  .queue-when { width: auto; display: flex; gap: 6px; align-items: baseline; flex-basis: 100%; }
  /* The time is its own line here, so there is no column to line the note up with. */
  .queue-list > li > .queue-blocker { margin-inline-start: 0; }
  .queue-filters { flex-basis: 100%; }
  .queue-filters .select { flex: 1 1 10rem; max-width: none; }
}

/* ---------- Reports ---------- */
.report-controls { flex-direction: row; flex-wrap: wrap; gap: var(--s1) var(--s2); align-items: center; justify-content: space-between; }
.report-filters { display: flex; flex-wrap: wrap; gap: var(--s0); margin-inline-start: auto; }
.report-filters .select { width: auto; max-width: 16rem; }
.report-custom { display: flex; flex-wrap: wrap; gap: var(--s1); align-items: flex-end; flex-basis: 100%; }
.report-custom[hidden] { display: none; }
.report-custom .field { margin: 0; }
.report-window { margin: 0; }
.report-pipeline { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.report-channels > li { align-items: flex-start; flex-wrap: wrap; }
.report-channels .list-main { flex: 1 1 16rem; }
.share-bars { display: grid; gap: var(--s0); flex: 0 1 16rem; min-width: 12rem; }
.share-bar .meter-top { font-size: var(--t-1); }
.share-bar + .share-bar .meter-fill { background: var(--ok); }
.report-top > li { align-items: flex-start; }
.report-notes { font-size: var(--t-1); margin-top: var(--s1); }
/* How a number moved on the period before: green up, amber down, the words beside the arrow. */
.stat-delta { display: flex; gap: 4px; align-items: center; margin: 0; font-size: var(--t-1); color: var(--ink-2); }
.stat-delta[data-tone="ok"] { color: var(--ok); }
.stat-delta[data-tone="warn"] { color: var(--warn); }
/* "What works": a group too small to rank is shown, dimmed, never crowned. */
.report-breakdown > li { align-items: center; }
.report-breakdown .list-main { flex: 1 1 12rem; min-width: 0; }
.report-breakdown > li[data-enough="false"] .meter-fill { opacity: .45; }
.report-breakdown .meter-top .num { white-space: nowrap; }
/* An odd card out takes the whole row rather than sitting beside a gap (§0.13). */
.report-breakdowns > :last-child:nth-child(odd) { grid-column: 1 / -1; }
/* Reports → Tests (L.6): one card per test; the verdict's mark beside the
   sentence; the test and control periods as a strip that wraps on a phone. */
.report-tests-group { margin: var(--s2) 0 0; font-size: var(--t1); }
.report-test { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.report-test > p { margin: 0; overflow-wrap: anywhere; }
.report-test-head { display: flex; gap: var(--s1); align-items: flex-start; }
.report-test-head h3 { margin: 0; font-size: var(--t1); text-wrap: balance; min-width: 0; }
.report-test-mark { flex: none; color: var(--ink-2); }
.report-test-mark[data-tone="ok"] { color: var(--ok); }
.report-test-mark[data-tone="warn"] { color: var(--warn); }
.report-test-mark[data-tone="bad"] { color: var(--bad); }
.report-test-chips { display: flex; flex-wrap: wrap; gap: var(--s0); margin: 0; }
.report-test-periods { display: flex; flex-wrap: wrap; gap: var(--s0); margin: 0; padding: 0; list-style: none; }
.report-test-periods > li { display: flex; flex-direction: column; flex: 1 1 7.5rem; min-width: 0; padding: var(--s0) var(--s1); border: var(--rule-w) solid var(--rule); border-radius: var(--radius-sm); font-size: var(--t-1); }
.report-test-periods > li[data-arm="test"] { background: var(--accent-soft); border-color: var(--accent-soft); color: var(--accent-ink); }
.report-test-periods > li[data-now] { outline: 2px solid var(--focus); outline-offset: 1px; }
.report-test-periods small { color: inherit; opacity: .8; white-space: nowrap; }
.report-test-result { display: flex; flex-direction: column; gap: var(--s0); padding: var(--s1) var(--s2); border-radius: var(--radius-sm); background: var(--paper-2); }
.report-test-result > * { margin: 0; }
.report-test-verdict { font-weight: 600; }
/* Reports → Memory (L.7): a learning's card is a test's, with its kind on its edge. */
.report-learning { border-inline-start: 3px solid var(--rule); }
.report-learning[data-kind="works"] { border-inline-start-color: var(--ok); }
.report-learning[data-kind="fails"] { border-inline-start-color: var(--bad); }
.report-learning[data-kind="fact"] { border-inline-start-color: var(--accent); }
.report-memory-hint { margin: 0; }
.report-memory-best > li { overflow-wrap: anywhere; }
.report-memory-gone > summary { cursor: pointer; font-weight: 600; }
.report-memory-gone ul { margin-block: var(--s1) 0; }
.report-memory-gone li { overflow-wrap: anywhere; color: var(--ink-2); }
/* AI reports (L.8): the periods as a list of buttons, the open report's story, its numbers and next steps. */
.report-ai-write-block > .hint { margin: var(--s0) 0 0; }
.report-ai-write { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s1) var(--s2); }
.report-ai-write .field { flex: 1 1 14rem; min-width: 0; margin: 0; }
.report-ai-mail { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3); border: 0; padding: 0; margin: 0; min-width: 0; }
.report-ai-mail > legend { font-weight: 600; padding: 0; margin-block-end: var(--s0); }
.report-ai-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s0); }
.report-ai-item { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s0) var(--s2); width: 100%; min-width: 0; text-align: start; font: inherit; color: inherit; background: none; border: 1px solid var(--rule); border-radius: var(--radius-control); padding: var(--s1) var(--s2); cursor: pointer; }
.report-ai-item:hover { border-color: var(--accent); }
.report-ai-item[aria-current="true"] { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.report-ai-when { white-space: nowrap; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.report-ai-headline { flex: 1 1 16rem; min-width: 0; overflow-wrap: anywhere; }
.report-ai-story { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s2) var(--s3); }
.report-ai-part h3, .report-ai-numbers h3, .report-ai-next h3 { margin: 0 0 var(--s0); font-size: 1rem; }
.report-ai-part p { margin: 0; overflow-wrap: anywhere; }
.report-ai-steps { margin: 0; padding-inline-start: 1.25rem; display: flex; flex-direction: column; gap: var(--s1); }
.report-ai-step p { margin: 0; overflow-wrap: anywhere; }
.report-ai-history > summary { cursor: pointer; font-weight: 600; }
@media (max-width: 640px) {
  .report-ai-story { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .report-filters { margin-inline-start: 0; flex-basis: 100%; }
  .report-filters .select { flex: 1 1 10rem; max-width: none; }
  .share-bars { flex-basis: 100%; }
}

/* A campaign's page: the summary and its side cards keep their own height
   instead of being stretched to each other with their rows pulled apart. */
.detail-split { align-items: start; }
/* Tasks, budget and ads share one row under the full-width calendar; auto-fit
   lets two cards split it in halves instead of leaving an empty third. */
.detail-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: var(--gap); align-items: start; }
.detail-split > .stack { align-content: start; }
@media (max-width: 640px) {
  /* A phone pays for every inset twice (both sides), and these boxes nest: a card holds a row,
     the row opens the post panel, the panel holds the editor, the editor the media library.
     At 375px that stacked up to 81px a side and squeezed the library to 57% of the screen.
     So on a phone ONE box keeps a side inset — the card — and the ones inside it mark
     themselves with a rule or a tint, not with more room. */
  .post-panel { padding: var(--s1) 0 0; border-width: var(--rule-w) 0 0; border-radius: 0; background: none; }
  .post-edit { padding: 0; background: none; box-shadow: none; border-radius: 0; }
  .post-preview { padding: var(--s1); }
  .photo-search, .cal-edit, .cal-thread, .starter { padding: var(--s1); }
  /* The row's note is inside a card too: less padding, and its list indents by a bullet's
     width, not by a desktop's 24px (it started at 102px of a 375px screen). */
  .queue-blocker { gap: 10px; padding: 10px 12px; }
  .bullets { padding-inline-start: 1.1em; }
  /* Two choices, two even halves: a wrapped pill reads as a blob (the publishing tabs' lesson). */
  .library-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; border-radius: var(--radius-control); }
  .library-tabs label { display: grid; }
  .library-tabs span { justify-content: center; padding: 6px 8px; white-space: normal; text-align: center; border-radius: calc(var(--radius-control) - 3px); }
  /* The three qualities have long labels: one even row each, as a wrapped pill reads as a blob. The three
     shapes are short words and share one row. */
  .picture-maker .segmented { display: grid; grid-template-columns: minmax(0, 1fr); width: 100%; border-radius: var(--radius-control); }
  .picture-maker .segmented label { display: grid; }
  .picture-maker .segmented span { justify-content: center; padding: 8px; white-space: normal; text-align: center; border-radius: calc(var(--radius-control) - 3px); }
  .picture-maker .picture-shape { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .post-media img, .post-video { width: 84px; height: 84px; }
}
/* Below 400px the card itself runs edge to edge (the kit), so its 16px pad is the one inset a
   side. A tinted box inside it does the same — out to the card's edges, radius off, the card's
   pad as its own — so its words line up with the card's instead of stepping in once more. */
@media (max-width: 400px) {
  .photo-search, .cal-edit, .cal-thread, .starter, .post-preview, .queue-blocker {
    margin-inline: calc(-1 * var(--card-pad));
    padding-inline: var(--card-pad);
    border-radius: 0;
    border-inline-width: 0;
  }
}
/* A select is as wide as its longest option unless told otherwise; a channel
   with a long name must not push a filter past the card's edge on a phone. */
.report-filters, .queue-filters { min-width: 0; max-width: 100%; }
.report-filters .select, .queue-filters .select { min-width: 0; }

/* ---------- Inbox: comments under the brand's posts (views/inbox.js) ----------
   A row is the publishing queue's row with a stranger's words in it: who,
   where and when on one line, the comment itself, the writer's reading as
   marks, the post it is under and the reply waiting. The comment opens under
   its row on the post panel's frame. */
.inbox-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s1); margin: 0; color: var(--ink-3); font-size: var(--t-1); }
.inbox-author { color: var(--ink); font-size: var(--t0); overflow-wrap: anywhere; }
.inbox-body { margin: 2px 0 0; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; max-width: var(--measure); }
.inbox-marks { margin: 4px 0 0; }
/* Send and Reply side by side at the row's end, not stacked into a tower. */
@media (min-width: 641px) { .list > .inbox-row > .btn-row { flex: none; flex-wrap: nowrap; } }
/* Wraps rather than clips, so "View on …" stays reachable on a phone; the excerpt is cut short in views/inbox.js. */
.inbox-under { display: block; overflow-wrap: anywhere; }
.inbox-under .ci, .inbox-note .ci, .inbox-reply small .ci, .inbox-foot .ci { --ci-size: 14px; vertical-align: -2px; }
.inbox-note { color: var(--ink-2); }
/* The reply as it stands: set off from the stranger's words by the brand's own edge. */
.inbox-reply { display: grid; gap: 2px; margin-top: 4px; padding: 6px var(--s1); border-inline-start: 3px solid var(--accent-ink); border-radius: var(--radius-sm); background: var(--accent-wash); max-width: var(--measure); }
.inbox-reply p { margin: 0; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.inbox-foot { margin: var(--s2) 0 0; }
.inbox-more { justify-content: center; margin-top: var(--s1); }
.inbox-more:empty { display: none; }
/* Choosing several comments (public/js/inbox-bulk.js): a box in front of each row, and a bar above the list with
   "all shown", the count and the acts. The refusals of the last act stay under the bar, scrolling past a dozen. */
.inbox-pick { display: flex; flex: none; align-items: center; align-self: flex-start; min-block-size: 44px; }
.inbox-bulk { display: grid; gap: var(--s1); margin-block: var(--s1); }
.inbox-bulk-bar, .inbox-bulk-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s0) var(--s1); min-width: 0; }
.inbox-bulk-actions[hidden], .inbox-bulk-actions > [hidden] { display: none; }
.inbox-bulk-actions .select { width: auto; max-width: 16rem; min-width: 0; }
.inbox-bulk .alert-body { max-block-size: 14rem; overflow-y: auto; }
.inbox-bulk-fail { display: block; overflow-wrap: anywhere; }
.inbox-subhead { margin: 0; font-size: var(--t0); }
/* The thread: a stranger's comments plain, the brand's own replies on its wash and edge, the one opened marked. */
.inbox-thread .thread-item { padding: 6px var(--s1); border-radius: var(--radius-control); }
.inbox-thread .thread-item .list-icon { width: 28px; height: 28px; border-radius: 8px; }
.inbox-thread .thread-item .list-icon .ci { --ci-size: 14px; }
.inbox-thread .thread-item[data-ours] { background: var(--accent-wash); box-shadow: inset 3px 0 0 var(--accent-ink); }
/* The brand's own replies are marked on the reading edge: the right one in Arabic or Hebrew. */
:root[dir="rtl"] .inbox-thread .thread-item[data-ours] { box-shadow: inset -3px 0 0 var(--accent-ink); }
.inbox-thread .thread-item[aria-current="true"] { background: var(--paper-2); box-shadow: inset 0 0 0 var(--rule-w) var(--rule-strong); }
.inbox-note-form { padding: var(--s1) 0 0; }
/* How each channel is answered: the channel, what its setting means, and the three-way switch. */
/* Saved replies: the card's rows keep the body's line breaks, and the picker is a select with its button beside it. */
.saved-reply-body { white-space: pre-wrap; max-width: var(--measure); color: var(--muted); margin: 0; }
.saved-reply-pick { display: flex; gap: var(--space-2, .5rem); align-items: center; flex-wrap: wrap; }
.saved-reply-pick > :first-child { flex: 1 1 14rem; min-width: 0; }
.inbox-policy { align-items: center; }
.inbox-policy-say { max-width: var(--measure); }
.inbox-policy-pick[aria-busy="true"] { opacity: .6; pointer-events: none; }
@media (max-width: 640px) {
  /* Five views in rows of two; the fifth takes its row rather than leaving a hole (§0.13). */
  .inbox-tabs label:last-child { grid-column: 1 / -1; }
  .inbox-policy { align-items: flex-start; }
  .inbox-policy-pick { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; border-radius: var(--radius-control); }
  .inbox-policy-pick label { display: grid; }
  .inbox-policy-pick span { justify-content: center; padding: 4px 6px; border-radius: calc(var(--radius-control) - 3px); }
}

/* ---------- Campaigns: the month calendar (views/campaign-calendar.js) ----------
   The look of the fabls.io calendar (castomapi-try site-kit/try.css `.cal*`) in the kit's
   tokens, so light, dark and high contrast are each the theme's own. Its classes are `mcal-`
   because `.cal-*` already names the List view's rows, which the month view opens in a dialog. */
.cal-card { gap: var(--s2); }
.cal-card > .card-head { margin-bottom: 0; }
.cal-switch { align-self: flex-start; max-width: 100%; }

/* The posting mode (campaign-cadence.js): the choice, what it means, and — after a change on a
   planned campaign — the way to plan again in it. */
.cadence-block { display: grid; gap: var(--s1); }
.cadence-pick { justify-self: start; max-width: 100%; }
.cadence-explain { margin: 0; max-width: var(--measure); }
.cadence-read { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; margin: 0; color: var(--ink); }
.cadence-offer { display: grid; gap: var(--s0); padding: var(--s1) var(--s2); border-radius: var(--radius-control); background: var(--accent-wash); }
.cadence-offer[hidden] { display: none; }
.cadence-offer .hint { margin: 0; color: var(--ink-2); }
.campaign-about { margin: 0 0 var(--s2); color: var(--ink-2); max-width: var(--measure); white-space: pre-line; overflow-wrap: anywhere; }
/* "Extend campaign" asks, it does not warn: its dialog's picture wears the accent, not the danger tone. */
.extend-art { background: var(--accent-soft); color: var(--accent-ink); }
.extend-hint { display: block; }
.extend-group { margin: 0; padding-inline: 0; padding-bottom: 0; border-inline: 0; border-bottom: 0; }

.mcal {
  --p1: var(--chart-2); --p2: var(--chart-4); --p3: var(--chart-6); --p4: var(--chart-3); --p5: var(--chart-5); --p6: var(--chart-1);
  display: grid; gap: var(--s2); min-width: 0;
}
.mcal [data-p="1"] { --pc: var(--p1); } .mcal [data-p="2"] { --pc: var(--p2); } .mcal [data-p="3"] { --pc: var(--p3); }
.mcal [data-p="4"] { --pc: var(--p4); } .mcal [data-p="5"] { --pc: var(--p5); } .mcal [data-p="6"] { --pc: var(--p6); }

/* The bar: the months shown and the arrows either side, then how many to show and Extend. */
.mcal-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s1) var(--s2); }
.mcal-nav { display: flex; align-items: center; gap: var(--s0); min-width: 0; }
.mcal-range { margin: 0; min-width: 0; font-size: var(--t1); color: var(--ink); overflow-wrap: anywhere; }
.mcal-step:disabled { opacity: .4; cursor: default; }
.mcal-tools { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); }
.mcal-show { display: flex; align-items: center; gap: var(--s0); }
.mcal-show-label { color: var(--ink-3); font-size: var(--t-1); font-weight: 600; }
.mcal-show-pick span { justify-content: center; min-width: 2.6em; padding-inline: 10px; }

/* The head: pillars on one side; the posts in view and the channel filters on the other. */
.mcal-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s3); align-items: end; }
.mcal-pillars { display: flex; flex-wrap: wrap; gap: 6px var(--s2); margin: 0; padding: 0; list-style: none; }
.mcal-pillar { display: inline-flex; align-items: center; gap: 8px; color: var(--ink-2); font-size: var(--t-1); }
.mcal-pillar i { width: 10px; height: 10px; border-radius: 3px; background: var(--pc); flex: none; }
.mcal-side { display: grid; justify-items: end; gap: var(--s0); min-width: 0; }
.mcal-count { display: flex; align-items: baseline; gap: 6px; margin: 0; color: var(--ink-3); font-size: var(--t-1); }
.mcal-total { color: var(--ink); font-size: var(--t3); line-height: 1; letter-spacing: -.02em; }
.mcal-filter { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.mcal-chan {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px; max-width: 100%; padding: 4px 12px;
  border: var(--rule-w) solid var(--rule); border-radius: var(--radius-pill); background: var(--paper-2);
  color: var(--ink-2); font: inherit; font-size: var(--t-1); cursor: pointer;
}
.mcal-chan .ci { --ci-size: 16px; flex: none; }
.mcal-chan-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mcal-chan b { color: var(--ink); }
.mcal-chan:hover { background: var(--hover); }
.mcal-chan:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; }
/* Off is said twice — faded and struck through — never by the colour alone. */
.mcal-chan[aria-pressed="false"] { opacity: .55; }
.mcal-chan[aria-pressed="false"] .mcal-chan-name { text-decoration: line-through; }
@media (pointer: coarse) { .mcal-chan { min-height: 44px; } }

/* The months, Monday first. Under dir="rtl" the grid itself runs right to left, so Monday
   stands on the right and the week reads in the language's direction with no rule of its own. */
.mcal-months { display: grid; gap: var(--s3); min-width: 0; }
.mcal-month { display: grid; gap: var(--s0); min-width: 0; }
.mcal-month-name { margin: 0; color: var(--ink-2); font-size: var(--t0); }
/* One month shown: the bar already names it, so its own heading stays for screen readers only. */
.mcal-month:only-child > .mcal-month-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.mcal-grid { border: var(--rule-w) solid var(--rule); border-radius: var(--radius-control); overflow: hidden; background: var(--paper-2); }
.mcal-dow, .mcal-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
/* The last row's own bottom rules tuck under the grid's edge rather than doubling it. */
.mcal-days { margin-bottom: calc(-1 * var(--rule-w)); }
.mcal-dow { background: var(--field); border-bottom: var(--rule-w) solid var(--rule); }
.mcal-dow span { padding: 6px 8px; overflow: hidden; color: var(--ink-3); font-size: var(--t-2); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; text-overflow: ellipsis; white-space: nowrap; }
/* Spaced letters break Arabic's joined script apart. */
:root[dir="rtl"] .mcal-dow span { letter-spacing: 0; }
.mcal-day {
  position: relative; display: grid; grid-template-rows: auto 1fr; gap: 4px; min-width: 0; min-height: 112px; padding: 6px;
  border-inline-end: var(--rule-w) solid var(--rule); border-bottom: var(--rule-w) solid var(--rule);
  transition: background-color var(--dur) var(--ease);
}
.mcal-days > :nth-child(7n) { border-inline-end: 0; }
.mcal-day.is-weekend { background: color-mix(in oklab, var(--field) 55%, transparent); }
/* Not a day of the campaign: hatched like the padding days, and nothing lands on it. */
.mcal-day:is(.is-blank, .is-out) { background: repeating-linear-gradient(-45deg, transparent 0 7px, var(--field) 7px 8px); }
.mcal-day.is-out .mcal-date { opacity: .55; }
.mcal-date { display: inline-flex; align-items: baseline; gap: 4px; justify-self: start; padding: 1px 6px; border-radius: var(--radius-pill); color: var(--ink-3); font-size: var(--t-1); font-weight: 700; line-height: 1.5; }
.mcal-wd { display: none; }
.mcal-day.is-today .mcal-date { background: var(--accent); color: var(--on-accent); }
.mcal-day.is-pulse .mcal-date { animation: mcal-pulse .7s var(--ease); }
@keyframes mcal-pulse { 35% { transform: scale(1.3); background: var(--accent-soft); color: var(--accent-ink); } }
@media (prefers-reduced-motion: reduce) { .mcal-day.is-pulse .mcal-date { animation: none; } }
.mcal-posts { display: grid; gap: 4px; align-content: start; min-width: 0; margin: 0; padding: 0; list-style: none; }
.mcal-posts > li[hidden] { display: none; }

/* Occasions: holidays, commercial days and the brand's own dates, as small markers under the day's
   number — never cards, nothing moves onto or off them. The kind is a dot in a tone and, for a
   screen reader, a sentence; colour is never the only word (the name is always beside the dot). */
.mcal-day.has-occasions { grid-template-rows: auto auto 1fr; }
.mcal-occasions { display: grid; gap: 2px; align-content: start; min-width: 0; margin: 0; padding: 0; list-style: none; }
.mcal-occ { display: flex; align-items: center; gap: 4px; min-width: 0; color: var(--ink-2); font-size: var(--t-2); line-height: 1.3; }
.mcal-occ-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--rule-strong); }
.mcal-occ[data-kind="public"] .mcal-occ-dot { background: var(--warn); }
.mcal-occ[data-kind="commercial"] .mcal-occ-dot { background: var(--info); }
.mcal-occ[data-kind="own"] { color: var(--accent-ink); font-weight: 700; }
.mcal-occ[data-kind="own"] .mcal-occ-dot { border-radius: 2px; background: var(--accent-ink); }
.mcal-occ-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mcal-occ.is-more { color: var(--ink-3); font-weight: 700; }
.mcal-occ-toggle { font-size: var(--t-1); }
.occasion-list .cal-meta { align-items: center; }
.occasion-form .check { min-height: 44px; }
/* The strategy (strategy-card.js, strategy-progress.js): a row of controls that wraps rather than overflows, a mix row of
   channel · number · confirmation, and the pillar total that says plainly when it is not 100. */
.strategy-row { align-items: end; flex-wrap: wrap; }
.strategy-row .field { flex: 1 1 12rem; min-width: 0; }
.strategy-target { white-space: nowrap; }
.strategy-persona-edit { display: grid; gap: var(--s1); min-width: 0; margin: 0; }
.strategy-persona-edit legend { padding: 0 var(--s0); font-weight: 700; }
.strategy-mix-edit > li { display: grid; grid-template-columns: minmax(7rem, 1fr) minmax(10rem, 2fr) auto; align-items: center; gap: var(--s1); }
.strategy-mix-count { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s1); min-width: 0; }
.strategy-mix-count .input { inline-size: 6rem; }
.strategy-mix-edit li[data-included="false"] .strategy-mix-count small { color: var(--ink-3); }
.strategy-sum { margin: 0; font-weight: 700; font-variant-numeric: tabular-nums; }
.strategy-sum[data-tone="ok"] { color: var(--ok); }
.strategy-sum[data-tone="warn"] { color: var(--warn); }
.strategy-progress:empty { display: none; }
.strategy-goals > li[data-tone="ok"] .meter-fill { background: var(--ok); }
@media (max-width: 560px) {
  .strategy-mix-edit > li { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  /* The month is a list of days here: markers sit in the column beside the number, above the posts. */
  .mcal-occasions, .mcal-day.has-occasions .mcal-posts { grid-column: 2; }
  .mcal-day.has-occasions { grid-template-rows: auto; }
}

/* A card: channel and time on top, the words under them, the pillar's colour down its reading
   edge, the state as a dot (and in its name, for a screen reader). */
.mcal-card {
  --pc: var(--rule-strong);
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "icons time marks" "title title title";
  align-items: center; gap: 2px 5px; width: 100%; padding: 5px 6px;
  border: 0; border-inline-start: 3px solid var(--pc); border-radius: var(--radius-sm);
  background: var(--field); color: var(--ink); font: inherit; font-size: var(--t-2); line-height: 1.25; text-align: start;
  cursor: pointer; touch-action: manipulation; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  transition: background-color var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.mcal.can-move .mcal-card { cursor: grab; }
/* Each day is the measure its cards fit: beside the campaign's side cards a day is about 80px
   wide, where an icon, "12:00 PM" and a dot do not share a line — so a narrow day gives the time
   a line of its own rather than letting it run into the next day. */
.mcal-day:not(.is-blank) { container-type: inline-size; }
@container (max-width: 124px) {
  .mcal-card { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "icons marks" "time time" "title title"; padding: 4px 4px 4px 5px; }
}
.mcal-card:hover { background: var(--accent-soft); }
.mcal-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.mcal-icons { grid-area: icons; display: inline-flex; align-items: center; }
.mcal-icons .ci { --ci-size: 14px; flex: none; color: var(--ink-2); }
.mcal-more { margin-inline-start: 3px; color: var(--ink-3); font-size: var(--t-2); font-weight: 700; }
.mcal-time { grid-area: time; min-width: 0; overflow: hidden; color: var(--ink-3); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.mcal-title { grid-area: title; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; font-weight: 600; }
.mcal-marks { grid-area: marks; display: inline-flex; align-items: center; gap: 3px; }
.mcal-marks .ci { --ci-size: 12px; color: var(--accent-ink); }
.mcal-tone { width: 7px; height: 7px; border-radius: 50%; background: var(--rule-strong); box-shadow: 0 0 0 1px var(--paper-2); }
.mcal-tone[data-tone="ok"] { background: var(--ok); }
.mcal-tone[data-tone="accent"] { background: var(--accent-ink); }
.mcal-tone[data-tone="info"] { background: var(--info); }
.mcal-tone[data-tone="warn"] { background: var(--warn); }
.mcal-tone[data-tone="bad"] { background: var(--bad); }
.mcal-card[data-state="published"] { background: color-mix(in oklab, var(--ok) 12%, var(--field)); }
.mcal-card[data-state="failed"] { background: color-mix(in oklab, var(--bad) 12%, var(--field)); }
.mcal-card:is([data-state="skipped"], [data-state="superseded"]) .mcal-title { color: var(--ink-3); text-decoration: line-through; text-decoration-thickness: 1px; }
/* A burst — one message on several channels at once — is a small deck: its channels overlap in
   a row and a second card shows under it, offset toward the reading edge's far side. */
.mcal-card.is-burst { box-shadow: 3px 3px 0 -1px var(--paper-2), 3px 3px 0 0 var(--rule-strong); }
:root[dir="rtl"] .mcal-card.is-burst { box-shadow: -3px 3px 0 -1px var(--paper-2), -3px 3px 0 0 var(--rule-strong); }
.mcal-card.is-burst .mcal-icons .ci { border-radius: 50%; background: var(--paper-2); box-shadow: 0 0 0 1.5px var(--field); }
.mcal-card.is-burst .mcal-icons .ci + .ci { margin-inline-start: -4px; }

/* Moving: the card lifted, the ghost under the pointer, the day it would land on. */
.mcal-card.is-held { outline: 3px solid var(--accent-soft); outline-offset: 1px; }
.mcal-card.is-held:focus-visible { outline-color: var(--focus); outline-style: dashed; }
.mcal-card.is-dragging { opacity: .35; }
.mcal-card.is-busy { opacity: .7; cursor: progress; }
/* Placed by the pointer's own coordinates, which are physical in every direction: `left`, not inline-start. */
.mcal-ghost { position: fixed; left: 0; top: 0; z-index: 1000; pointer-events: none; box-shadow: var(--shadow-pop); opacity: .95; }
.mcal-day.is-target { background: var(--accent-soft); box-shadow: inset 0 0 0 2px var(--accent-ink); }
.mcal-day.is-refused { background: color-mix(in oklab, var(--bad) 10%, transparent); box-shadow: inset 0 0 0 2px var(--bad); cursor: not-allowed; }
:root[data-theme^="contrast"] .mcal-day:is(.is-target, .is-refused) { outline: 3px solid var(--ink); outline-offset: -3px; }
.mcal-hint { margin: 0; }

/* What a card opens: the slot rows of the List view, in the kit's dialog, as wide as a post needs. */
.mcal-dialog { width: min(760px, calc(100vw - 32px)); }
.mcal-dialog .dialog-head > .icon-btn { margin-top: -6px; }
.mcal-dialog .dialog-body { padding-bottom: var(--s3); }

/* 640 (kit step): the head stacks, its filters start where the words start. */
@media (max-width: 640px) {
  .mcal-head { grid-template-columns: minmax(0, 1fr); }
  .mcal-side { justify-items: start; }
  .mcal-filter { justify-content: flex-start; }
}
/* 560 (kit step, where a card's pad drops to the gutter's): seven columns would leave a post a
   word wide, so a month becomes a list of the campaign's days, the weekday beside each number.
   Empty days stay, shorter, so there is still somewhere to drop a post. */
@media (max-width: 560px) {
  .mcal-dow { display: none; }
  .mcal-days { grid-template-columns: minmax(0, 1fr); }
  .mcal-day { grid-template-columns: 4.6rem minmax(0, 1fr); grid-template-rows: auto; align-items: start; min-height: 0; padding: 8px 10px; border-inline-end: 0; }
  .mcal-day:is(.is-blank, .is-out) { display: none; }
  .mcal-day.is-empty { padding-block: 4px; }
  .mcal-wd { display: inline; font-weight: 600; }
  .mcal-card { grid-template-columns: auto auto minmax(0, 1fr) auto; grid-template-areas: "icons time title marks"; padding: 8px 10px; font-size: var(--t-1); }
  .mcal-title { -webkit-line-clamp: 1; }
}

/* A paid slot (rule 12zzl, views/campaign-calendar.js `paid`): a PROPOSAL, so it is a dashed card with the megaphone and
   the amount a day, never mistaken for a post and never dragged. Accepted, its edge turns solid and green. */
.mcal-card.mcal-paid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "icons" "amount" "title"; border-inline-start-style: dashed; border-inline-start-color: var(--accent-ink); background: color-mix(in oklab, var(--accent-ink) 8%, var(--field)); }
.mcal.can-move .mcal-card.mcal-paid { cursor: pointer; }
.mcal-card.mcal-paid[data-state="accepted"] { border-inline-start-style: solid; border-inline-start-color: var(--ok); }
.mcal-amount { grid-area: amount; justify-self: start; color: var(--accent-ink); font-weight: 700; white-space: nowrap; }
@media (max-width: 560px) {
  .mcal-card.mcal-paid { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "icons title amount"; }
  .mcal-amount { justify-self: end; }
}
.paid-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--s0); align-items: start; }
.paid-prefilled { color: var(--accent-ink); font-weight: 600; }

/* ---------- The brand timeline (views/brand-timeline.js) ----------
   Four filters above the line, wrapping on a phone; the channel a line
   touched sits beside its time; "Show more" and the history file below it. */
.timeline-filters { display: flex; flex-wrap: wrap; gap: var(--s0); min-width: 0; max-width: 100%; margin-block-end: var(--s1); }
.timeline-filters .select { flex: 1 1 9rem; width: auto; min-width: 0; max-width: 16rem; }
.tl-meta { color: var(--ink-3); font-size: var(--t-1); overflow-wrap: anywhere; }
.timeline-status:empty { display: none; }
.timeline-more { margin-block-start: var(--s1); }
.timeline-more:not(:has(> :not([hidden]))) { display: none; }
.timeline-file { display: grid; gap: var(--s0); margin-block-start: var(--s2); padding-block-start: var(--s2); border-block-start: 1px solid var(--rule); }
.timeline-file .hint { margin: 0; max-width: var(--measure); }
@media (max-width: 640px) { .timeline-filters .select { max-width: none; } }

/* A channel's own page (views/channel-page.js): its platform's mark beside its name. */
.channel-title { display: inline-flex; align-items: center; gap: var(--s0); min-width: 0; overflow-wrap: anywhere; }
.channel-lead { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s0); }

/* A channel's health (views/channel-health.js): each reason on a tinted line
   in its tone, its way out beside it, stacking under it on a phone. */
.health-list { display: grid; gap: var(--s0); margin: 0; padding: 0; list-style: none; }
.health-list li { --tone: var(--warn); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s0) var(--s1); padding: var(--s0) var(--s1); border-inline-start: 3px solid var(--tone); border-radius: var(--radius-control); background: color-mix(in oklab, var(--tone) 8%, var(--paper-2)); }
.health-list li[data-tone="bad"] { --tone: var(--bad); }
.health-list li p { flex: 1 1 16rem; min-width: 0; margin: 0; overflow-wrap: anywhere; }

/* The pause button (pause.js): the banner above every screen while the brand is paused, and the list
   of posts that missed their time after a resume. The top bar's button turns the warning colour while paused. */
.pause-banner { margin-block-end: var(--s2); }
.pause-banner[hidden] { display: none; }
.pause-button[data-paused] { color: var(--warn); }
.pause-posts { display: grid; gap: var(--s0); margin: 0; padding: 0; list-style: none; }
.pause-posts li { display: grid; gap: 2px; padding: var(--s0) var(--s1); border-radius: var(--radius-control); background: var(--field); overflow-wrap: anywhere; }

/* Setup Studio's guide (views/profile-kit.js): the kit's own step list, each
   step with the kit's pieces it needs — a label, the text or the picture's
   download, and its copy button — wrapping to one column on a phone. */
.setup-steps p { margin: 0; color: var(--ink-2); max-width: var(--measure); }
.setup-pieces { display: grid; gap: 6px; margin-block-start: 6px; }
.setup-piece { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s1); min-width: 0; padding: 6px var(--s1); border-radius: var(--radius-control); background: var(--field); }
.setup-piece-group { display: grid; gap: 6px; min-width: 0; }
.setup-piece-label { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; font-size: var(--t-1); font-weight: 600; color: var(--ink-2); }
.setup-piece-value { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; white-space: pre-line; }

/* ---------- New post (new-post.js): one post from scratch, to one channel or several ---------- */
.dialog.new-post-dialog { width: min(640px, calc(100vw - 32px)); }
/* Step two holds the full post editor, which the queue gives a whole row's width. */
.dialog.new-post-dialog.new-post-full { width: min(880px, calc(100vw - 32px)); }
.new-post-editors { display: grid; gap: var(--s2); min-width: 0; }
/* Wraps rather than scrolls: a scrolling box in a grid row collapses to nothing. */
.new-post-tabs { justify-self: start; max-width: 100%; flex-wrap: wrap; }
.new-post-channels { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); gap: 6px var(--s1); border: 0; padding: 0; margin: 0; min-width: 0; }
.new-post-channels legend { margin-block-end: 6px; }
.new-post-channels .check { min-width: 0; }
.new-post-channels .check > span { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; min-width: 0; overflow-wrap: anywhere; }
.new-post-channels .check small { flex: none; white-space: nowrap; }
/* "Add a picture" / "Add a video" (post-media.js): the icon and the words on one line, the icon centred on it, as the channel rows above. */
.check-media > span { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.new-post .hint[data-tone="bad"] { color: var(--bad); }
.new-post .segmented { justify-self: start; }
.repurpose [hidden] { display: none; }
.repurpose-when { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: var(--s1); min-width: 0; }
.repurpose-when input { min-width: 0; inline-size: 100%; box-sizing: border-box; }
.repurpose-when .field { min-width: 0; }
.repurpose-file-chosen { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s1); min-width: 0; overflow-wrap: anywhere; }
.repurpose-summary[data-tone="bad"] { color: var(--bad); }
.repurpose-progress { display: grid; gap: var(--s1); }
.repurpose-source-name { display: flex; align-items: center; gap: 6px; margin: 0; min-width: 0; overflow-wrap: anywhere; }
.repurpose-progress .meter-track { height: 8px; }
.repurpose-progress-line { margin: 0; font-variant-numeric: tabular-nums; }
/* A launch (launch.js): its three steps, then the money per channel and the ad proposal. */
.launch .repurpose-when select { min-width: 0; inline-size: 100%; }
.launch-ads { display: grid; gap: var(--s1); min-width: 0; }
.launch-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.launch-steps li { display: grid; grid-template-columns: auto 1fr; align-items: start; gap: 8px; min-width: 0; }
.launch-steps li > div { display: grid; min-width: 0; overflow-wrap: anywhere; }
.launch-steps li small { color: var(--muted); }
.launch-steps li[data-tone="ok"] > [data-ci] { color: var(--ok); }
.launch-steps li[data-tone="bad"] > [data-ci], .launch-steps li[data-tone="bad"] small { color: var(--bad); }
.launch-steps li[data-state="working"] > [data-ci] { animation: launch-spin 1.2s linear infinite; }
@keyframes launch-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .launch-steps li[data-state="working"] > [data-ci] { animation: none; } }
.launch-extra { display: grid; gap: 6px; min-width: 0; }
.launch-extra > .btn { justify-self: start; }
.launch-extra h3 { margin: var(--s1) 0 0; }
.launch-extra p, .launch-extra ul { margin: 0; }
.launch-split { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.launch-split li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px var(--s1); min-width: 0; overflow-wrap: anywhere; }
.new-post-thumb { display: flex; align-items: center; gap: var(--s1); margin: 0; }
.new-post-thumb img { inline-size: 96px; block-size: 96px; object-fit: cover; border-radius: var(--radius-control); }
/* ---------- Ideas (views/ideas.js): the backlog, and the strip of days an idea is dropped on ---------- */
.idea-days { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 92px), 1fr)); gap: 6px; }
.idea-day { display: grid; gap: 2px; justify-items: start; padding: 8px 10px; min-width: 0; border: var(--rule-w) dashed var(--rule-strong); border-radius: var(--radius-control); }
.idea-day small { color: var(--muted); }
.idea-day[data-busy="true"] small { color: var(--ink); }
.idea-day.is-target { border-style: solid; border-color: var(--accent-ink); background: var(--accent-soft); }
.idea-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: var(--s1); }
.idea-row[draggable="true"] { cursor: grab; }
.idea-row.is-dragged { opacity: 0.55; }
.idea-title { overflow-wrap: anywhere; }
.idea-note { margin: 2px 0 6px; color: var(--muted); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.idea-placed { list-style: none; margin: 6px 0; padding: 0; display: grid; gap: 4px; }
.idea-placed li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }
.idea-row[data-status="dropped"] .idea-title { color: var(--muted); text-decoration: line-through; }
@media (max-width: 640px) { .idea-row { grid-template-columns: minmax(0, 1fr); } }

/* Screenshots in the kit's Report a bug dialog (js/bug-shots.js). Logical properties so the remove button mirrors in RTL. */
.bug-shots { display: grid; gap: var(--s1); }
.bug-shots-note { margin: 0; color: var(--ink-3); font-size: var(--t-1); }
.bug-shots-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s1); }
.bug-shots-list:empty { display: none; }
.bug-shot { position: relative; inline-size: 112px; block-size: 84px; min-width: 0; }
.bug-shot img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; border-radius: var(--radius-control); box-shadow: inset 0 0 0 var(--rule-w) var(--rule); }
.bug-shot-remove { position: absolute; inset-block-start: 4px; inset-inline-end: 4px; background: var(--paper); }
.bug-shots.is-drop { outline: 2px dashed var(--accent-ink); outline-offset: 4px; border-radius: var(--radius-control); }
