/* ProAgri Client Portal - the post frame and the Posts screen.
   Everything here is prefixed .pa-post-.

   Two visual layers, deliberately kept apart:

     1. THE MOCK  (.pa-post-mock and its skins) - a REPLICA of what publishes
        under the client's own account, so it wears neutral platform chrome and
        the CLIENT's mark. No ProAgriMedia colour goes inside it: the avatar ring
        is a hairline, not a red halo, because a red ring around the client's
        logo is us branding their post. Where the mock needs a dark ground (the
        story phone body, the letterbox behind an off-ratio creative, the slide
        counter) it takes --pa-brand-accent, which is navy: a dark device surface
        rather than an accent. No Instagram or Facebook logos or trademarks: the
        affordances are generic outline glyphs.

     2. THE PORTAL (.pa-post-strip, .pa-post-review, the documents block) - ours,
        and ProAgriMedia CI. Navy is the chrome: the strip that frames the replica
        is a solid navy bar, section icons are navy, and "approved" is navy
        because this CI has no green. Red is reserved for action - the primary
        button, a focus ring, a count that is wrong. Yellow, all 10% of it, means
        one thing only: waiting on the client.

   Only --pa-* tokens. Local --pa-post-* vars below derive from them. */

.pa-post {
  --pa-post-mock-pad: var(--pa-space-4);
  --pa-post-chrome: var(--pa-text-muted);

  /* THE DEVICE TONE - the one dark ground inside the replica.
     The brief puts --pa-brand-accent under the phone body, the letterbox behind
     an off-ratio creative and the slide counter. Straight navy at 100% did not
     survive the look: a saturated navy slab wrapped around the client's artwork
     stops reading as a phone and starts reading as a ProAgri card, which is
     exactly the misrepresentation the carve-out forbids. Pulling it toward the
     CI's own black keeps it a palette colour - navy and black, nothing invented
     - while giving it the neutral weight a device surface needs. Every dark
     ground in this file resolves here so the three can never drift apart. */
  --pa-post-device: color-mix(in srgb, var(--pa-brand-accent) 62%, var(--pa-black));

  display: flex;
  flex-direction: column;
  min-width: 0;
  /* A feed post is never wider than about 470px on the real thing. Letting the
     mock stretch to a wide host (a wide modal, a single-column grid on a large
     screen) blows the media up to a 1000px square and stops looking like a post
     at all, so the frame caps itself and centres in whatever it is given. */
  width: 100%;
  max-width: 560px;
  margin-inline: auto;
  background: var(--pa-surface);
  /* Depth from shadow, not from an outline. The hairline stays only because it
     is what carries the status colour on the edge of the card; it is the one
     border on this screen and it is never heavier than 1px. */
  border: 1px solid var(--pa-border);
  border-radius: var(--pa-radius-lg);
  box-shadow: var(--pa-shadow);
  overflow: hidden;
  transition: box-shadow var(--pa-dur) var(--pa-ease), border-color var(--pa-dur) var(--pa-ease);
}

.pa-post:hover { box-shadow: var(--pa-shadow-lg); }

/* Status on the edge, in the CI's own vocabulary. Approved is NAVY, not green -
   there is no green in this palette and inventing one to mean "done" would be
   the one colour on the screen that belongs to nobody. Changes requested is RED:
   it used to be amber, which collided with the yellow that means "waiting on
   you", so the two states a client most needs to tell apart looked alike. */
.pa-post.is-approved { border-color: color-mix(in srgb, var(--pa-success) 45%, var(--pa-border)); }
.pa-post.is-changes_requested { border-color: color-mix(in srgb, var(--pa-danger) 45%, var(--pa-border)); }

.pa-post :focus-visible,
.pa-view-posts :focus-visible {
  outline: 2px solid var(--pa-brand-primary);
  outline-offset: 2px;
  border-radius: var(--pa-radius-sm);
}

.pa-post-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── 1. Portal strip: says "what follows is a preview" ─────────────────────── */
.pa-post-strip {
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  padding: var(--pa-space-3) var(--pa-space-4);
  /* Solid navy, because this line is the portal SPEAKING - "what follows is a
     replica, not the real account". A tinted band read as part of the post; a
     navy bar reads as the frame around it, which is exactly the job. It was
     red-tinted, and red on a label that marks nothing actionable is the misuse
     the CI guideline calls out by name. */
  background: var(--pa-brand-accent);
  color: var(--pa-on-dark-muted);
  font-size: var(--pa-text-xs);
  font-weight: 600;
  letter-spacing: var(--pa-track-eyebrow);
  text-transform: uppercase;
}

.pa-post-strip .pa-icon { color: var(--pa-on-dark); flex: none; }

/* ── 2. The platform mock ──────────────────────────────────────────────────── */
.pa-post-mock {
  background: var(--pa-surface);
  color: var(--pa-text);
}

.pa-post-glyph { flex: none; }

/* Profile row, shared shape across both skins */
.pa-post-ighead,
.pa-post-fbhead {
  display: flex;
  align-items: center;
  gap: var(--pa-space-3);
  padding: var(--pa-post-mock-pad);
}

.pa-post-fbhead { padding-bottom: var(--pa-space-2); }

.pa-post-avatar {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--pa-radius-pill);
  background: var(--pa-surface);
  padding: 2px;
  /* A HAIRLINE, NOT A BRAND RING. This is the client's own mark on a replica of
     their own account, and it used to sit inside a red halo drawn from
     --pa-brand-ring. That is us painting our colour onto their post, which is
     the one thing the frame interior may never do. */
  box-shadow: 0 0 0 1px var(--pa-border-strong);
  overflow: hidden;
}

.pa-post-avatar.is-square { border-radius: var(--pa-radius-sm); box-shadow: 0 0 0 1px var(--pa-border); }

.pa-post-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: inherit;
}

.pa-post-avatar-text {
  font-size: var(--pa-text-sm);
  font-weight: 700;
  text-transform: uppercase;
  /* Their initials, in ink. Same reason as the ring above. */
  color: var(--pa-text);
}

.pa-post-idblock {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}

.pa-post-handle {
  font-size: var(--pa-text-sm);
  font-weight: 700;
  color: var(--pa-text);
  overflow-wrap: anywhere;
}

.pa-post-page {
  font-size: var(--pa-text-base);
  font-weight: 700;
  color: var(--pa-text);
  overflow-wrap: anywhere;
}

.pa-post-sub {
  display: flex;
  align-items: center;
  gap: var(--pa-space-1);
  font-size: var(--pa-text-xs);
  color: var(--pa-text-muted);
}

.pa-post-dotsbtn { flex: none; color: var(--pa-text-faint); display: inline-flex; }

/* Media: the aspect box is reserved up front so nothing shifts when the image
   decodes. Every ratio the platforms actually use is here. */
.pa-post-mediabox { position: relative; }

.pa-post-media {
  position: relative;
  overflow: hidden;
  background: var(--pa-surface-3);
  isolation: isolate;
}

.pa-post-media.is-r11 { aspect-ratio: 1 / 1; }
.pa-post-media.is-r45 { aspect-ratio: 4 / 5; }
.pa-post-media.is-r916 { aspect-ratio: 9 / 16; }

.pa-post-track {
  position: relative;
  z-index: 0;
  display: flex;
  width: 100%;
  height: 100%;
  transition: transform var(--pa-dur-slow) var(--pa-ease);
}

.pa-post-slide { flex: 0 0 100%; width: 100%; height: 100%; }

.pa-post-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

.pa-post-nomedia {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--pa-space-2);
  color: var(--pa-text-faint);
  font-size: var(--pa-text-sm);
}

.pa-post-counter {
  position: absolute;
  z-index: 2;
  top: var(--pa-space-3);
  right: var(--pa-space-3);
  padding: 3px var(--pa-space-2);
  border-radius: var(--pa-radius-pill);
  background: color-mix(in srgb, var(--pa-post-device) 78%, transparent);
  color: var(--pa-surface);
  font-size: var(--pa-text-xs);
  font-weight: 600;
  line-height: 1.5;
  backdrop-filter: blur(4px);
}

/* Carousel arrows stay visible at rest. Hiding them until hover would make the
   second and third image undiscoverable on touch, and hover-only affordances are
   an accessibility anti-pattern - so they only deepen on hover. */
/* Centred with top/calc, NOT transform: components.css gives every .pa-btn a
   translateY(1px) on :active, which would replace a centring transform on
   mousedown - the button jumps half its height away and mouseup lands on the
   image, so no click event is ever produced. */
.pa-post-arrow.pa-btn {
  position: absolute;
  z-index: 2;
  top: calc(50% - 22px);
  width: 44px;
  height: 44px;
  min-width: 44px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: var(--pa-radius-pill);
  background: color-mix(in srgb, var(--pa-surface) 86%, transparent);
  color: var(--pa-text);
  border: 1px solid var(--pa-border);
  box-shadow: var(--pa-shadow-sm);
  backdrop-filter: blur(4px);
  transition: background var(--pa-dur) var(--pa-ease), box-shadow var(--pa-dur) var(--pa-ease);
}

.pa-post-arrow.is-prev { left: var(--pa-space-2); }
.pa-post-arrow.is-next { right: var(--pa-space-2); }

.pa-post-arrow.pa-btn:hover {
  background: var(--pa-surface);
  box-shadow: var(--pa-shadow);
}

.pa-post-dots {
  display: flex;
  justify-content: center;
  gap: var(--pa-space-1);
  padding: var(--pa-space-3) 0 0;
}

.pa-post-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--pa-radius-pill);
  background: var(--pa-border-strong);
  transition: background var(--pa-dur) var(--pa-ease), transform var(--pa-dur) var(--pa-ease);
}

.pa-post-dot.is-on { background: var(--pa-brand-accent); transform: scale(1.25); }

/* Engagement affordances. Decorative and aria-hidden: they are part of the
   picture of the post, not controls, so they get no hover or pointer. */
.pa-post-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--pa-space-3) var(--pa-post-mock-pad) var(--pa-space-2);
  color: var(--pa-text);
}

.pa-post-actions-left { display: flex; align-items: center; gap: var(--pa-space-4); }
.pa-post-act { display: inline-flex; color: var(--pa-text); }

.pa-post-likes {
  margin: 0;
  padding: 0 var(--pa-post-mock-pad);
  font-size: var(--pa-text-sm);
  font-weight: 700;
  color: var(--pa-text);
}

.pa-post-when {
  margin: 0;
  padding: var(--pa-space-2) var(--pa-post-mock-pad) var(--pa-space-4);
  font-size: var(--pa-text-xs);
  color: var(--pa-text-faint);
  text-transform: uppercase;
  letter-spacing: var(--pa-track-eyebrow);
}

/* Caption */
.pa-post-caption-wrap { display: flex; flex-direction: column; }

.pa-post-caption {
  margin: var(--pa-space-2) 0 0;
  padding: 0 var(--pa-post-mock-pad);
  font-size: var(--pa-text-sm);
  line-height: 1.55;
  color: var(--pa-text);
  /* Clamped state collapses the newlines, otherwise a caption that opens with a
     blank line burns one of its two teaser lines on nothing and the ellipsis
     lands alone. The real line breaks come back when it expands. */
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.pa-post-caption.is-open {
  display: block;
  white-space: pre-wrap;
  -webkit-line-clamp: none;
  line-clamp: none;
  overflow: visible;
}

.pa-post-caption.is-empty { color: var(--pa-text-faint); font-style: italic; }
.pa-post-caption-handle { font-weight: 700; margin-right: var(--pa-space-1); }

.pa-post-more {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0 0 0 var(--pa-space-1);
  padding: 0 var(--pa-space-3);
  background: none;
  border: 0;
  color: var(--pa-text-muted);
  font: inherit;
  font-size: var(--pa-text-sm);
  cursor: pointer;
}

.pa-post-more:hover { color: var(--pa-text); text-decoration: underline; }

/* Facebook skin: caption above the media, media edge to edge */
.pa-post-fb .pa-post-caption { padding: 0 var(--pa-post-mock-pad); margin-bottom: var(--pa-space-3); }
.pa-post-fb .pa-post-caption-wrap { margin-bottom: var(--pa-space-2); }

.pa-post-fbmedia { margin: 0; }

.pa-post-fbcount {
  display: flex;
  align-items: center;
  gap: var(--pa-space-1);
  margin: 0;
  padding: var(--pa-space-3) var(--pa-post-mock-pad) var(--pa-space-2);
  font-size: var(--pa-text-xs);
  color: var(--pa-text-muted);
  border-bottom: 1px solid var(--pa-border);
}

.pa-post-fbcount .pa-post-glyph { color: var(--pa-info); }

.pa-post-fbbar {
  display: flex;
  align-items: center;
  justify-content: space-around;
  gap: var(--pa-space-2);
  padding: var(--pa-space-2) var(--pa-space-2) var(--pa-space-3);
  color: var(--pa-text-muted);
}

.pa-post-fbact {
  display: inline-flex;
  align-items: center;
  gap: var(--pa-space-2);
  font-size: var(--pa-text-sm);
  font-weight: 600;
}

/* Story / reel: a phone-ish 9:16 frame on a neutral stage */
.pa-post-story {
  padding: var(--pa-space-5) var(--pa-space-4);
  background: var(--pa-surface-3);
}

.pa-post-phone {
  position: relative;
  width: min(276px, 100%);
  margin-inline: auto;
  border-radius: var(--pa-radius-lg);
  overflow: hidden;
  background: var(--pa-post-device);
  box-shadow: var(--pa-shadow-lg);
}

/* Creatives are authored square. Cropping one into a 9:16 story would slice the
   headline in half and read as a broken preview, so the story frame letterboxes
   it on the dark ground - which is what the platform does with an off-ratio
   upload anyway. */
.pa-post-phone .pa-post-media { background: var(--pa-post-device); }
.pa-post-phone .pa-post-img { object-fit: contain; }

.pa-post-progress {
  position: absolute;
  top: var(--pa-space-2);
  left: var(--pa-space-3);
  right: var(--pa-space-3);
  height: 3px;
  border-radius: var(--pa-radius-pill);
  background: color-mix(in srgb, var(--pa-surface) 34%, transparent);
  overflow: hidden;
}

.pa-post-progress-fill {
  display: block;
  width: 38%;
  height: 100%;
  border-radius: inherit;
  background: var(--pa-surface);
}

.pa-post-storyhead {
  position: absolute;
  top: calc(var(--pa-space-2) + var(--pa-space-3));
  left: var(--pa-space-3);
  right: var(--pa-space-3);
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  padding-bottom: var(--pa-space-4);
  background: linear-gradient(to bottom, color-mix(in srgb, var(--pa-post-device) 64%, transparent), transparent);
  color: var(--pa-surface);
}

.pa-post-storyhead .pa-post-avatar {
  width: 30px;
  height: 30px;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--pa-surface) 80%, transparent);
}

.pa-post-storyhandle { font-size: var(--pa-text-xs); font-weight: 700; }
.pa-post-storyage { font-size: var(--pa-text-xs); opacity: 0.8; }

/* ── 3. The portal review footer ───────────────────────────────────────────── */
.pa-post-review {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-4);
  padding: var(--pa-space-5);
  /* The tray the portal's question sits in. It reads as recessed under the white
     replica above it, which is the separation this file has always wanted; the
     old red 8% wash bought the same separation with the brand's action colour,
     on a surface where nothing is an action until you reach the buttons. */
  background: var(--pa-surface-3);
  border-top: 1px solid var(--pa-border);
}

.pa-post-review.is-compact { gap: var(--pa-space-2); padding: var(--pa-space-4); }

.pa-post-reviewtag {
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  font-size: var(--pa-text-xs);
  font-weight: 700;
  letter-spacing: var(--pa-track-eyebrow);
  text-transform: uppercase;
  color: var(--pa-text-muted);
}

.pa-post-reviewtag .pa-icon { color: var(--pa-brand-accent); }
.pa-post-reviewtag .pa-badge { margin-left: auto; text-transform: none; letter-spacing: 0; }

.pa-post-reviewrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pa-space-3);
  flex-wrap: wrap;
}

.pa-post-meta {
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  margin: 0;
  font-size: var(--pa-text-sm);
  color: var(--pa-text-muted);
}

.pa-post-meta .pa-icon { flex: none; }

/* Every panel inside the tray is a white card floating on it: no border, a soft
   shadow, a real corner. Three of them (this, the date, the publication) used to
   be bordered grey boxes on a tinted ground, which is the dated-intranet shape
   this redesign exists to leave behind. */
.pa-post-vcaption {
  padding: var(--pa-space-4);
  background: var(--pa-surface);
  border-radius: var(--pa-radius);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-vcaption-label {
  margin: 0;
  font-size: var(--pa-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--pa-track-eyebrow);
  color: var(--pa-text-faint);
}

.pa-post-vcaption .pa-post-caption { padding: 0; }
.pa-post-vcaption .pa-post-more { margin-left: 0; padding-left: 0; }

.pa-post-edited {
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  flex-wrap: wrap;
  margin: 0;
}

.pa-post-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--pa-space-2);
  background: none;
  border: 0;
  color: var(--pa-brand-primary);
  font: inherit;
  font-size: var(--pa-text-sm);
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

.pa-post-link:hover { color: var(--pa-brand-primary-hover); }

.pa-post-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pa-space-2);
}

.pa-post-buttons .pa-btn { min-height: 44px; }

/* Approved is navy and reads as settled. It is the only "done" colour this CI
   has, and it is deliberately the same navy as the chrome. */
.pa-post-approved {
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  margin: 0;
  padding: var(--pa-space-4);
  background: var(--pa-success-soft);
  border-radius: var(--pa-radius);
  box-shadow: var(--pa-shadow-sm);
  color: var(--pa-success);
  font-size: var(--pa-text-sm);
  font-weight: 700;
}

.pa-post-hint {
  display: flex;
  align-items: flex-start;
  gap: var(--pa-space-2);
  margin: 0;
  font-size: var(--pa-text-xs);
  line-height: 1.5;
  color: var(--pa-text-muted);
}

.pa-post-hint .pa-icon { flex: none; margin-top: 1px; color: var(--pa-warning); }

/* Caption editor and change composer */
.pa-post-editor,
.pa-post-composer {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-3);
  margin: var(--pa-space-3) var(--pa-post-mock-pad) var(--pa-space-2);
  padding: var(--pa-space-4);
  background: var(--pa-surface);
  /* A red hairline on an open composer is the one border on this screen that
     earns a colour: it is the live, unfinished action the client is mid-way
     through, and it disappears the moment they send or cancel. */
  border: 1px solid var(--pa-brand-ring);
  border-radius: var(--pa-radius);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-review .pa-post-editor,
.pa-post-review .pa-post-composer { margin: 0; }

/* A label naming a panel is chrome, so it is navy. Red here would be red on a
   word that marks nothing you can press. */
.pa-post-editor-label {
  margin: 0;
  font-size: var(--pa-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--pa-track-eyebrow);
  color: var(--pa-brand-accent);
}

.pa-post-editor-hint {
  margin: 0;
  font-size: var(--pa-text-xs);
  color: var(--pa-text-muted);
}

.pa-post-editor-actions,
.pa-post-composer-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pa-space-2);
}

.pa-post-editor-actions .pa-btn,
.pa-post-composer-actions .pa-btn { min-height: 44px; }

.pa-post-ta {
  width: 100%;
  min-height: 96px;
  padding: var(--pa-space-3);
  background: var(--pa-surface);
  border: 1px solid var(--pa-border-strong);
  border-radius: var(--pa-radius-sm);
  color: var(--pa-text);
  font: inherit;
  font-size: var(--pa-text-sm);
  line-height: 1.55;
  resize: vertical;
}

.pa-post-ta:focus-visible { border-color: var(--pa-brand-primary); }
.pa-post-ta.is-invalid { border-color: var(--pa-danger); background: var(--pa-danger-soft); }

.pa-post-round-label {
  margin: 0;
  font-size: var(--pa-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--pa-track-eyebrow);
  color: var(--pa-brand-accent);
}

/* What a change request covers, stated at the composer. It replaced a
   three-way radio group (image / description / both): the description was never
   worth one of three rounds because the client edits it themselves, so the
   choice is gone and this sentence says what is left. */
.pa-post-scope {
  display: flex;
  align-items: flex-start;
  gap: var(--pa-space-2);
  margin: 0;
  padding: var(--pa-space-3);
  font-size: var(--pa-text-sm);
  line-height: 1.55;
  color: var(--pa-text);
  background: var(--pa-accent-soft);
  border-radius: var(--pa-radius);
}

.pa-post-scope .pa-icon { flex: none; margin-top: 2px; color: var(--pa-brand-accent); }

/* The error line keeps its space whether or not it has text. Collapsing it on
   blur moved everything below it up by a line, which pulled the Send button out
   from under the pointer between mousedown and mouseup - the click silently went
   nowhere. Reserve the row, never toggle it. */
.pa-post-err {
  margin: 0;
  min-height: 1.3em;
  font-size: var(--pa-text-xs);
  font-weight: 600;
  line-height: 1.3;
  color: var(--pa-danger);
}

.pa-post-file {
  width: 100%;
  font-size: var(--pa-text-sm);
  color: var(--pa-text-muted);
}

.pa-post-file::file-selector-button {
  min-height: 44px;
  margin-right: var(--pa-space-3);
  padding: 0 var(--pa-space-4);
  background: var(--pa-surface-3);
  border: 1px solid var(--pa-border-strong);
  border-radius: var(--pa-radius-sm);
  color: var(--pa-text);
  font: inherit;
  font-size: var(--pa-text-sm);
  font-weight: 600;
  cursor: pointer;
}

.pa-post-chips { display: flex; flex-wrap: wrap; gap: var(--pa-space-2); }
.pa-post-chips:empty { display: none; }

.pa-post-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--pa-space-2);
  max-width: 100%;
  padding: var(--pa-space-1) var(--pa-space-1) var(--pa-space-1) var(--pa-space-1);
  background: var(--pa-surface-2);
  border: 1px solid var(--pa-border);
  border-radius: var(--pa-radius-pill);
}

.pa-post-chip-img {
  width: 32px;
  height: 32px;
  border-radius: var(--pa-radius-pill);
  object-fit: cover;
  flex: none;
}

.pa-post-chip-name {
  font-size: var(--pa-text-xs);
  color: var(--pa-text-muted);
  max-width: 15ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pa-post-chip-x.pa-btn {
  width: 32px;
  min-width: 32px;
  height: 32px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: var(--pa-radius-pill);
}

/* Change-request history */
.pa-post-history {
  padding-top: var(--pa-space-3);
  border-top: 1px solid var(--pa-border);
}

.pa-post-history-title {
  margin: 0 0 var(--pa-space-2);
  font-size: var(--pa-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--pa-track-eyebrow);
  color: var(--pa-text-muted);
}

.pa-post-rounds {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pa-post-round {
  padding: var(--pa-space-4);
  background: var(--pa-surface);
  border-radius: var(--pa-radius);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-round-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--pa-space-2);
  margin-bottom: var(--pa-space-2);
}

.pa-post-round-no { font-size: var(--pa-text-sm); font-weight: 700; color: var(--pa-text); }
.pa-post-round-time { margin-left: auto; font-size: var(--pa-text-xs); color: var(--pa-text-faint); }

.pa-post-round-note {
  margin: 0;
  font-size: var(--pa-text-sm);
  line-height: 1.55;
  color: var(--pa-text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.pa-post-round-atts { display: flex; flex-wrap: wrap; gap: var(--pa-space-2); margin-top: var(--pa-space-2); }

.pa-post-att {
  width: 56px;
  height: 56px;
  padding: 0;
  background: none;
  border: 1px solid var(--pa-border);
  border-radius: var(--pa-radius-sm);
  overflow: hidden;
  cursor: pointer;
  transition: border-color var(--pa-dur) var(--pa-ease);
}

.pa-post-att:hover { border-color: var(--pa-brand-primary); }
.pa-post-att img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Approve confirmation */
.pa-post-confirm { display: flex; flex-direction: column; gap: var(--pa-space-3); }
.pa-post-confirm-title { margin: 0; font-size: var(--pa-text-lg); color: var(--pa-text); }
.pa-post-confirm-note { margin: 0; font-size: var(--pa-text-sm); line-height: 1.55; color: var(--pa-text-muted); }
.pa-post-confirm-actions { display: flex; flex-wrap: wrap; gap: var(--pa-space-2); justify-content: flex-end; }
.pa-post-confirm-actions .pa-btn { min-height: 44px; }

.pa-post-modal { display: block; }

/* ── Compact variant, for grid and list hosts ──────────────────────────────── */
.pa-post.is-compact { --pa-post-mock-pad: var(--pa-space-3); }
.pa-post.is-compact .pa-post-avatar { width: 32px; height: 32px; }
.pa-post.is-compact .pa-post-actions { padding-block: var(--pa-space-2); }
.pa-post.is-compact .pa-post-actions-left { gap: var(--pa-space-3); }
.pa-post.is-compact .pa-post-likes,
.pa-post.is-compact .pa-post-caption { font-size: var(--pa-text-xs); }
.pa-post.is-compact .pa-post-story { padding: var(--pa-space-3); }
.pa-post.is-compact .pa-post-phone { width: min(190px, 100%); }
.pa-post.is-compact .pa-post-review { padding: var(--pa-space-4); }
.pa-post.is-compact .pa-post-strip { padding: var(--pa-space-2) var(--pa-space-3); }

/* ── The Posts screen ──────────────────────────────────────────────────────── */
.pa-view-posts { display: flex; flex-direction: column; gap: var(--pa-space-6); }

/* This is the page's one biggest title, and the type system gives that slot 700.
   ui.sectionHead builds an h2 for every section on every screen, so the weight
   cannot be raised in components.css without shouting from twelve places at
   once; it is raised here, scoped to this view. */
.pa-view-posts > .pa-sec-head > * > .pa-sec-title {
  font-size: var(--pa-text-xl);
  font-weight: 700;
  letter-spacing: var(--pa-track-tight);
  line-height: 1.15;
}

@media (min-width: 768px) {
  .pa-view-posts > .pa-sec-head > * > .pa-sec-title { font-size: var(--pa-text-2xl); }
}

/* ── Filters ────────────────────────────────────────────────────────
   Two segmented tracks rather than eight loose outlined buttons. The track is
   the floating-panel shape at control scale: a white pill lifted off the canvas
   on a soft shadow, with the chips living inside it and no borders anywhere. It
   also says which chips belong together, which eight identical outlines did not. */
.pa-post-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pa-space-3);
  align-items: center;
}

.pa-post-filtergroup {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pa-space-1);
  /* flex: 0 1 auto + min-width: 0 is what makes the shrink below REAL. Without
     the min-width a flex item refuses to shrink past its content, and a track
     that will not shrink paints outside the page instead. Same net as .pa-nav
     in shell.css. */
  flex: 0 1 auto;
  min-width: 0;
  padding: var(--pa-space-1);
  background: var(--pa-surface);
  border-radius: var(--pa-radius-pill);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-filtergroup.is-platform { margin-left: auto; }

.pa-post-chipbtn {
  display: inline-flex;
  align-items: center;
  gap: var(--pa-space-2);
  min-height: 44px;
  padding: 0 var(--pa-space-4);
  background: transparent;
  border: 0;
  border-radius: var(--pa-radius-pill);
  color: var(--pa-text-muted);
  font: inherit;
  font-size: var(--pa-text-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--pa-dur) var(--pa-ease), color var(--pa-dur) var(--pa-ease);
}

.pa-post-chipbtn:hover { background: var(--pa-surface-3); color: var(--pa-text); }

/* NAVY, NOT RED. A chosen filter is a state, not an action, and the nav bar
   above this screen already spends red on the active page. Two red pills of
   different meanings stacked one under the other taught the client nothing;
   navy here leaves red free to mean the one thing it should. */
.pa-post-chipbtn.is-on {
  background: var(--pa-brand-accent);
  color: var(--pa-brand-accent-contrast);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-chipbtn.is-on:hover {
  background: var(--pa-brand-accent-hover);
  color: var(--pa-brand-accent-contrast);
}

.pa-post-chipnum {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: var(--pa-radius-pill);
  background: var(--pa-surface-3);
  color: var(--pa-text-muted);
  font-size: var(--pa-text-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.pa-post-chipbtn.is-on .pa-post-chipnum {
  background: color-mix(in srgb, var(--pa-on-dark) 22%, transparent);
  color: var(--pa-on-dark);
}

/* The two counts that are not just information.
   Yellow is 10% of this palette and means exactly one thing: waiting on the
   client. A number of posts sitting unanswered IS that thing, so this is where
   the yellow gets spent. Red marks the other end - work the client has sent
   back. Both are set only when the count is non-zero (see posts.js): a yellow
   0 would be spending the scarcest colour in the CI on nothing at all.
   Both survive .is-on, because a filter you are standing inside must not stop
   telling you what it is counting. */
.pa-post-chipnum.is-waiting,
.pa-post-chipbtn.is-on .pa-post-chipnum.is-waiting {
  background: var(--pa-yellow);
  color: var(--pa-black);
}

.pa-post-chipnum.is-alert,
.pa-post-chipbtn.is-on .pa-post-chipnum.is-alert {
  background: var(--pa-danger);
  color: var(--pa-brand-primary-contrast);
}

.pa-post-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--pa-space-5);
  align-items: start;
}

.pa-post-clear { display: flex; justify-content: center; }

@media (min-width: 700px) {
  .pa-post-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--pa-space-6);
  }
}

@media (min-width: 1200px) {
  .pa-post-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 700px) {
  /* The tracks go full width and stack. Each one scrolls INSIDE ITSELF rather
     than wrapping: a pill track two rows deep stops reading as a segmented
     control, and rule 6 says wide content scrolls in its own container while the
     page body never does.

     `flex-wrap: nowrap` ON THE COLUMN IS LOAD-BEARING, AND LEAVING IT OFF IS
     WHAT BROKE THIS SCREEN. The base rule above wraps, and a column flex
     container that also wraps is MULTI-LINE: each line's cross size is then the
     width of the widest item on it, not the width of the container. So
     `align-items: stretch` faithfully stretched both tracks to their own 496px
     content width inside a 343px column and pushed the page 137px sideways -
     the one horizontally scrolling page in the portal. A single-line column has
     a definite cross size, so stretch resolves to the container and the
     overflow-x below is what absorbs the extra chips. */
  .pa-post-filters {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
  }

  .pa-post-filtergroup.is-platform { margin-left: 0; }

  .pa-post-filtergroup {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    /* No scrollbar. A native horizontal bar sitting inside a pill reads as a
       rendering fault rather than as an affordance; the half-cut chip at the
       edge is the affordance. Same treatment as .pa-nav. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* space-2, not space-1: this box CLIPS now, and a focus ring on the first or
       last chip is 2px of outline at 2px of offset. 4px of padding would shave
       it against the scroll edge. */
    padding: var(--pa-space-2);
  }

  .pa-post-filtergroup::-webkit-scrollbar { display: none; }

  .pa-post-chipbtn { flex: none; padding: 0 var(--pa-space-3); }
}

@media (max-width: 560px) {
  .pa-post-buttons .pa-btn,
  .pa-post-composer-actions .pa-btn,
  .pa-post-editor-actions .pa-btn { flex: 1 1 100%; justify-content: center; }
  .pa-post-review { padding: var(--pa-space-4); }
}

/* ══════════════════════════════════════════════════════════════════════════
   DOCUMENTS - the video cut, the design PDF, the loose files
   ══════════════════════════════════════════════════════════════════════════
   Deliberately NOT styled as part of the platform mock above it. The mock is a
   picture of a Facebook post; this is the actual artefact the client is being
   asked to sign off, so it reads as a portal panel: the app surface, the app
   border, no social chrome. It sits between the mock and the review controls
   because that is the reading order the decision needs - here is the thing, here
   is the question. */

.pa-post-docs {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-3);
  padding: var(--pa-space-4);
  border-top: 1px solid var(--pa-border);
  background: var(--pa-surface-2);
}

.pa-post-docs-head {
  display: flex;
  align-items: center;
  gap: var(--pa-space-2);
  color: var(--pa-text-muted);
}

.pa-post-docs-head .pa-icon { flex: none; color: var(--pa-brand-accent); }

.pa-post-docs-title {
  margin: 0;
  font-size: var(--pa-text-sm);
  font-weight: 700;
  letter-spacing: var(--pa-track-eyebrow);
  text-transform: uppercase;
  color: var(--pa-text-muted);
}

.pa-doc-list {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-4);
}

.pa-doc {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-3);
  padding: var(--pa-space-4);
  border-radius: var(--pa-radius);
  background: var(--pa-surface);
  box-shadow: var(--pa-shadow-sm);
  min-width: 0;
}

.pa-doc-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--pa-space-2);
  min-width: 0;
}

.pa-doc-type {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  padding: 3px 9px;
  border-radius: var(--pa-radius-pill);
  /* A file-type marker labels a thing. It does not act, so it is navy. */
  background: var(--pa-accent-soft-strong);
  color: var(--pa-brand-accent);
  font-size: var(--pa-text-xs);
  font-weight: 700;
  letter-spacing: var(--pa-track-eyebrow);
}

.pa-doc-type .pa-icon { flex: none; }

/* The filename can be long and machine-generated. It wraps rather than being
   truncated: a client asked to approve the right file needs to be able to read
   which one it is. */
.pa-doc-name {
  min-width: 0;
  flex: 1 1 12ch;
  font-size: var(--pa-text-sm);
  font-weight: 600;
  color: var(--pa-text);
  overflow-wrap: anywhere;
}

.pa-doc-note {
  flex: none;
  font-size: var(--pa-text-xs);
  color: var(--pa-text-muted);
}

/* Media sits on a dark stage so letterboxing on a 16:9 cut reads as intentional
   rather than as a rendering fault. */
.pa-doc-stage {
  display: flex;
  justify-content: center;
  border-radius: var(--pa-radius);
  /* Was a raw hsl(), which is a bug under rule 2 whatever it looked like. It is
     the same device tone as the phone body: dark enough that letterboxing a 16:9
     cut reads as intentional, and built only from navy and the CI's black. */
  background: var(--pa-post-device);
  overflow: hidden;
}

.pa-doc-player {
  display: block;
  width: 100%;
  max-height: 70vh;
  background: var(--pa-post-device);
}

.pa-doc-thumb-btn {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  min-width: 0;
  min-height: 44px;
}

.pa-doc-thumb-btn:focus-visible {
  outline: 2px solid var(--pa-brand-primary);
  outline-offset: 2px;
}

.pa-doc-thumb {
  display: block;
  width: 100%;
  max-height: 60vh;
  object-fit: contain;
}

.pa-doc-frame-wrap {
  border: 1px solid var(--pa-border);
  border-radius: var(--pa-radius);
  overflow: hidden;
  background: var(--pa-surface-3);
}

.pa-doc-frame {
  display: block;
  width: 100%;
  height: min(70vh, 620px);
  border: 0;
}

.pa-doc-hint {
  margin: 0;
  font-size: var(--pa-text-xs);
  line-height: 1.5;
  color: var(--pa-text-muted);
}

.pa-doc-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pa-space-2);
}

/* An anchor, not a button: open-in-new-tab, middle-click and long-press all have
   to keep working, and the browser only gives those to a real link. Sized to the
   44px tap floor the rest of the portal holds to. */
.pa-doc-open {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--pa-space-2);
  min-height: 44px;
  padding: 0 var(--pa-space-4);
  border: 1px solid var(--pa-border-strong);
  border-radius: var(--pa-radius-pill);
  background: var(--pa-surface);
  color: var(--pa-text);
  font-family: inherit;
  font-size: var(--pa-text-sm);
  font-weight: 600;
  text-decoration: none;
  transition: border-color var(--pa-dur-fast) var(--pa-ease), color var(--pa-dur-fast) var(--pa-ease);
}

.pa-doc-open .pa-icon { flex: none; }

.pa-doc-open:hover,
.pa-doc-open:focus-visible {
  border-color: var(--pa-brand-primary);
  color: var(--pa-brand-primary);
}

/* ── The honest failure ────────────────────────────────────────────────────
   A file that did not load gets the danger treatment, not a quiet placeholder,
   because it is also the thing that disables the Approve button above. The two
   have to read as connected or the disabled button looks like a portal bug. */
.pa-doc-failed {
  border-color: color-mix(in srgb, var(--pa-danger) 34%, var(--pa-border));
  background: var(--pa-danger-soft);
}

.pa-doc-fail {
  display: flex;
  gap: var(--pa-space-3);
  align-items: flex-start;
}

.pa-doc-fail-icon { flex: none; color: var(--pa-danger); line-height: 0; }

.pa-doc-fail-title {
  margin: 0 0 2px;
  font-size: var(--pa-text-sm);
  font-weight: 700;
  color: var(--pa-text);
}

.pa-doc-fail-note {
  margin: 0;
  font-size: var(--pa-text-sm);
  line-height: 1.55;
  color: var(--pa-text-muted);
}

/* ── The post date ─────────────────────────────────────────────────────── */

.pa-post-date {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-3);
  padding: var(--pa-space-4);
  border-radius: var(--pa-radius);
  background: var(--pa-surface);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-date-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--pa-text-xs);
  font-weight: 700;
  letter-spacing: var(--pa-track-eyebrow);
  text-transform: uppercase;
  color: var(--pa-text-muted);
}

.pa-post-date-label .pa-icon { flex: none; color: var(--pa-brand-accent); }

/* The native date input IS the control, on every width. A custom picker on a
   phone replaces a wheel the client already knows with one they do not, and
   type=date is what puts that wheel there. */
.pa-post-date-in {
  width: 100%;
  max-width: 260px;
  min-height: 44px;
  padding: 0 var(--pa-space-3);
  border: 1px solid var(--pa-border-strong);
  border-radius: var(--pa-radius-sm);
  background: var(--pa-surface);
  color: var(--pa-text);
  font-family: inherit;
  font-size: var(--pa-text-base);
}

.pa-post-date-in:focus-visible {
  outline: 2px solid var(--pa-brand-primary);
  outline-offset: 1px;
  border-color: var(--pa-brand-primary);
}

.pa-post-date-in:disabled {
  background: var(--pa-surface-3);
  color: var(--pa-text-faint);
}

.pa-post-date-flag {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--pa-space-2);
  margin: 0;
}

.pa-post-date-note {
  margin: 0;
  font-size: var(--pa-text-xs);
  line-height: 1.5;
  color: var(--pa-text-muted);
}

.pa-post-composer-date {
  display: flex;
  align-items: flex-start;
  gap: var(--pa-space-2);
  margin: 0;
  padding: var(--pa-space-2) var(--pa-space-3);
  border-radius: var(--pa-radius);
  background: var(--pa-info-soft);
  color: var(--pa-text);
  font-size: var(--pa-text-sm);
  line-height: 1.5;
}

.pa-post-composer-date .pa-icon { flex: none; margin-top: 2px; color: var(--pa-info); }

/* ── Magazine publication ──────────────────────────────────────────────── */

.pa-post-pub {
  display: flex;
  flex-direction: column;
  gap: var(--pa-space-3);
  padding: var(--pa-space-4);
  border: 1px solid transparent;
  border-radius: var(--pa-radius);
  background: var(--pa-surface);
  box-shadow: var(--pa-shadow-sm);
}

.pa-post-pub-label {
  margin: 0;
  font-size: var(--pa-text-xs);
  font-weight: 700;
  letter-spacing: var(--pa-track-eyebrow);
  text-transform: uppercase;
  color: var(--pa-text-muted);
}

.pa-post-pub-note {
  margin: 0;
  font-size: var(--pa-text-sm);
  line-height: 1.5;
  color: var(--pa-text-muted);
}

.pa-post-pub-opts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pa-space-2);
}

.pa-post-pub-opt {
  display: inline-flex;
  align-items: center;
  gap: var(--pa-space-2);
  flex: 1 1 150px;
  justify-content: center;
  min-height: 44px;
  padding: 0 var(--pa-space-4);
  border: 1.5px solid var(--pa-border-strong);
  border-radius: var(--pa-radius-pill);
  background: var(--pa-surface);
  color: var(--pa-text);
  font-family: inherit;
  font-size: var(--pa-text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: border-color var(--pa-dur-fast) var(--pa-ease), background var(--pa-dur-fast) var(--pa-ease);
}

/* The tick is the state, not colour alone: the two options are a hard either/or
   and the client has to be able to see which one they picked without relying on
   a hue they may not distinguish. */
.pa-post-pub-opt .pa-icon {
  flex: none;
  opacity: 0;
  transition: opacity var(--pa-dur-fast) var(--pa-ease);
}

/* Chosen is navy. Filling this pill red would put the loudest colour on the
   screen on a control that has already been answered, next to an Approve button
   that is the actual action. */
.pa-post-pub-opt.is-on {
  border-color: var(--pa-brand-accent);
  background: var(--pa-brand-accent);
  color: var(--pa-brand-accent-contrast);
}

.pa-post-pub-opt.is-on .pa-icon { opacity: 1; }

.pa-post-pub-opt:not(.is-on):hover:not(:disabled) { border-color: var(--pa-brand-accent); }

.pa-post-pub-opt:focus-visible {
  outline: 2px solid var(--pa-brand-primary);
  outline-offset: 2px;
}

.pa-post-pub-opt:disabled { cursor: default; opacity: 0.6; }

.pa-post-hint.is-blocked { color: var(--pa-text); }
.pa-post-hint.is-blocked .pa-icon { color: var(--pa-danger); }

@media (max-width: 700px) {
  /* Mobile browsers overwhelmingly refuse to render a PDF inside an iframe and
     draw an empty box instead. An empty box next to an Approve button is exactly
     the failure this work exists to remove, so the frame is not rendered at all
     below this width and the Open button carries the job. */
  .pa-doc-frame-wrap { display: none; }
  .pa-doc-open { width: 100%; }
  .pa-post-docs { padding: var(--pa-space-3); }
  .pa-doc-player { max-height: 56vh; }
  .pa-post-date-in { max-width: none; }
}

/* ── A post whose creative is a FILE, not an image ────────────────────────
   The aspect box reserves the shape a real image will fill. A video cut or a
   design PDF has no image and never will, so reserving a square left the client
   scrolling past most of a screen of empty grey to reach the only thing they
   were asked to look at. When documents carry the deliverable the box collapses
   to a single labelled strip that points down at them. */
.pa-post-mediabox.is-docsonly .pa-post-media {
  aspect-ratio: auto;
  min-height: 0;
  height: auto;
}

/* The placeholder is absolutely positioned inside the reserved box in the normal
   case. With the box collapsed it has to become static, or it inherits a zero
   height and disappears, leaving a caption and a like count with nothing between
   them, which reads as a broken post rather than an explained one. */
.pa-post-mediabox.is-docsonly .pa-post-nomedia {
  position: static;
  inset: auto;
  flex-direction: row;
  justify-content: flex-start;
  gap: var(--pa-space-2);
  padding: var(--pa-space-3);
  border-top: 1px solid var(--pa-border);
  font-size: var(--pa-text-sm);
}

/* The two PDF hints are mutually exclusive and keyed to the same 700px break
   that drops the frame itself, so the copy can never describe a preview that is
   not on screen. */
.pa-doc-hint.is-narrow { display: none; }

@media (max-width: 700px) {
  .pa-doc-hint.is-wide { display: none; }
  .pa-doc-hint.is-narrow { display: block; }
}

/* The publication card when nothing is chosen. live-data owns the approve block
   for this rule, so the card has to carry the warning on its own: an amber edge
   and a tinted ground make an unanswered required question read as unfinished
   from across the page, not as one more grey panel among several. */
.pa-post-pub.is-unanswered {
  border-color: color-mix(in srgb, var(--pa-warning) 42%, var(--pa-border));
  background: var(--pa-warning-soft);
}

.pa-post-pub-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--pa-space-2);
}

/* ── A creative image that did not load ──────────────────────────────────
   Fills the slide the image would have filled, so the carousel geometry, the
   dots and the counter all keep working and the client can still swipe past it
   to the images that DID arrive. Tinted danger rather than a neutral grey box:
   this is the thing disabling the Approve button below, and the two have to
   read as connected or the dead button looks like a portal fault. */
.pa-post-slide.is-failed {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--pa-danger-soft);
}

.pa-post-imgfail {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--pa-space-2);
  padding: var(--pa-space-5);
  text-align: center;
  color: var(--pa-text);
}

.pa-post-imgfail .pa-icon { flex: none; color: var(--pa-danger); }

.pa-post-imgfail-title {
  margin: 0;
  font-size: var(--pa-text-base);
  font-weight: 700;
}

.pa-post-imgfail-note {
  margin: 0;
  max-width: 34ch;
  font-size: var(--pa-text-sm);
  line-height: 1.5;
  color: var(--pa-text-muted);
}

/* ── A refused approve ───────────────────────────────────────────────────
   Sits under the buttons, where the client just clicked. Deliberately NOT the
   same treatment as .pa-post-hint.is-blocked: that one is a standing condition
   the client can read before acting, while this is the answer to something they
   just did, so it is filled rather than plain and it carries role=alert. */
.pa-post-refused {
  display: flex;
  align-items: flex-start;
  gap: var(--pa-space-2);
  margin: 0;
  padding: var(--pa-space-3);
  border: 1px solid color-mix(in srgb, var(--pa-danger) 34%, transparent);
  border-radius: var(--pa-radius);
  background: var(--pa-danger-soft);
  font-size: var(--pa-text-sm);
  font-weight: 500;
  line-height: 1.5;
  color: var(--pa-text);
}

.pa-post-refused .pa-icon { flex: none; margin-top: 2px; color: var(--pa-danger); }

/* Sits under the round counter in the composer. Quiet on purpose: it is
   reassurance, not an instruction, and it must not compete with the field the
   client is about to type in. */
.pa-post-round-note {
  margin: -4px 0 0;
  font-size: var(--pa-text-xs);
  line-height: 1.5;
  color: var(--pa-text-muted);
}
