/* 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); }
.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); }
.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 ---------- */
.row-link { color: var(--ink); font-weight: 650; text-decoration: none; }
.row-link:hover { text-decoration: underline; text-underline-offset: .18em; }

/* ---------- 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-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; }
.cal-slot { align-items: flex-start; }
.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 ----------
   Three in one row while ads wait (views/channels.js, features.js), so the 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; }

/* ---------- 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%; }
.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; }
/* 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; }
.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%; }
.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-list > li { align-items: flex-start; }
.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%; }
  .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); }
@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 side cards keep their own height beside a calendar
   months long, instead of being stretched to it with their rows pulled apart. */
.detail-split { 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); }
  .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; }
.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. */
.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); }
}
