/* =========================================================================
   Socials (5000 app) — design system overlay
   Brings the clean, modern "Socials Suite" (8000) look to the uploader tool
   WITHOUT changing any element IDs or feature logic.
   ========================================================================= */

:root {
  --brand-50:  #eef2ff;
  --brand-100: #e0e7ff;
  --brand-200: #c7d2fe;
  --brand-300: #a5b4fc;
  --brand-400: #818cf8;
  --brand-500: #6366f1;
  --brand-600: #4f46e5;
  --brand-700: #4338ca;

  --accent-400: #22d3ee;
  --accent-500: #06b6d4;

  --surface: #f8fafc;
  --surface-2: #f1f5f9;
  --border: #e2e8f0;
  --border-2: #cbd5e1;
  --text: #0f172a;
  --text-2: #475569;
  --text-3: #94a3b8;

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(15,23,42,.06);
  --shadow-md: 0 4px 12px rgba(15,23,42,.08);
  --shadow-lg: 0 12px 32px rgba(15,23,42,.12);
  --shadow-brand: 0 8px 24px rgba(99,102,241,.28);

  --danger: #e11d48;
  --danger-50: #fff1f2;
  --success: #059669;
  --success-50: #ecfdf5;

  --sidebar-w: 232px;
  --sidebar-w-min: 68px;
}

/* ---- brand logo artwork ----------------------------------------------------
   The real lockup (images/logo.png) replaces the old emoji mark + wordmark.
   Dark ink for light surfaces, images/logo-white.png (same artwork with the
   ink turned white) for the dark ones: the sidebar and the page footers.
   The height is set per surface with an inline style; width follows the
   786:227 aspect (and max-width keeps it inside a narrow container).          */
.brand-logo {
  display: block;
  height: 40px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

/* The page had the browser's default 8px body margin, so EVERY page (the app
   shell included) rendered inside a white frame: the header, the hero and the
   footer were inset from the viewport, and in the app the fixed sidebar and the
   content column started 8px apart. Nothing relies on that margin — the public
   sections carry their own 24px of side padding — so it is zeroed here, once.
   (`landing.css` then resets `height` to auto on the public pages, which scroll
   the document instead of an inner container.) */
html, body { height: 100%; margin: 0; }
body.dash-body {
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  background: var(--surface);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

/* ---- dashboard shell ----------------------------------------------------- */
.app-shell { display: flex; min-height: 100vh; }
/* Hide the whole app shell until the auth check resolves, so the
   dashboard/composer never flashes on screen before the login popup.
   Toggled by setAppShellVisible() in app.js (class .app-shell-hidden). */
.app-shell-hidden { display: none; }

.sidebar {
  width: var(--sidebar-w);
  background: #0f172a;
  color: #cbd5e1;
  position: fixed; top: 0; left: 0; bottom: 0;
  display: flex; flex-direction: column;
  z-index: 45;
  transition: transform .25s ease;
}
.sidebar .sb-brand {
  padding: 20px 18px 16px; display: flex; align-items: center; gap: 10px;
  /* CENTRED lockup. The mark is the only child and the sidebar is a fixed
     column, so a flex-start row left it sitting against the 18px padding with a
     visibly bigger gap on the other side (reported 2026-11-13: "center the logo
     here"). The collapsed variant (`.sb-min`, below) already centred it, so this
     also keeps the two states consistent. */
  justify-content: center;
  font-weight: 800; font-size: 17px; color: #fff; border-bottom: 1px solid #1e293b;
  /* It is a link to the public landing page now (see templates/index.html), so it
     must not pick up the default link colour/underline, and it needs a hover hint
     that it is clickable — the sidebar is otherwise all buttons. */
  text-decoration: none; transition: background .15s ease;
}
.sidebar .sb-brand:hover { background: rgba(255, 255, 255, .06); }
.sidebar .sb-brand .brand-mark {
  width: 34px; height: 34px; border-radius: 10px;
  background: linear-gradient(135deg, var(--brand-500), var(--accent-500));
  display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fff;
}
.sidebar .sb-brand .brand-logo { height: 34px; }
.sidebar .sb-nav { padding: 14px 12px; flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 3px;
  /* no visible scrollbar on the left main menu — keep scrolling, hide the bar */
  scrollbar-width: none; -ms-overflow-style: none; }
.sidebar .sb-nav::-webkit-scrollbar { width: 0; height: 0; display: none; }
.sidebar .sb-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: #64748b; padding: 10px 12px 5px; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.sidebar .sb-label img { flex: none; }
.sb-item {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; border-radius: 10px; color: #cbd5e1;
  font-weight: 500; font-size: 14px; cursor: pointer; border: none; background: transparent;
  width: 100%; text-align: start; transition: background .15s, color .15s;
}
.sb-item:hover { background: #1e293b; color: #fff; }
.sb-item.active { background: var(--brand-600); color: #fff; }
.sb-item.disabled { opacity: .45; cursor: not-allowed; }
.sb-item.disabled:hover { background: transparent; color: #cbd5e1; }
/* Photographers gets a warm marker of its own.
   It is the one entry in the sidebar that is a client-facing WORKFLOW rather
   than a composer or a list — you upload a session and send somebody a link —
   and it sat at the end of the Studio group looking like just another tool. The
   amber tint separates it from its neighbours without competing with the indigo
   that means "this is the page you are on": the ACTIVE state below still wins, so
   the highlight never makes it ambiguous which section is open.
   Amber rather than the literal yellow that was asked for: yellow (#facc15) on
   the navy sidebar glares, and amber reads as "photography" while matching the
   📸 it sits next to. */
.sb-item.pg-nav {
  background: rgba(245, 158, 11, .14);
  color: #fbbf24;
  font-weight: 600;
  /* An inset accent bar instead of a border: a border would change the item's
     box and shift the whole column by a pixel when it is added. */
  box-shadow: inset 3px 0 0 0 #f59e0b;
}
html[dir="rtl"] .sb-item.pg-nav { box-shadow: inset -3px 0 0 0 #f59e0b; }
.sb-item.pg-nav:hover { background: rgba(245, 158, 11, .24); color: #fde68a; }
/* Active: the same indigo every other section uses, so "where am I" stays
   consistent — but keep the amber bar so the section is still recognisable
   from the marker alone. */
.sb-item.pg-nav.active {
  background: var(--brand-600);
  color: #fff;
  box-shadow: inset 3px 0 0 0 #f59e0b;
}
html[dir="rtl"] .sb-item.pg-nav.active { box-shadow: inset -3px 0 0 0 #f59e0b; }
/* Collapsed to icons: the label is hidden, so the tint is the ONLY thing left
   saying which item this is — keep it. */
.app-shell.sb-min .sidebar .sb-item.pg-nav { background: rgba(245, 158, 11, .18); }
/* Anchor variant of .sb-item used for menu links that leave the SPA for a
   standalone page (e.g. the Activity & Logs dashboard at /activity). */
a.sb-item.sb-link { text-decoration: none; -webkit-tap-highlight-color: transparent; }
a.sb-item.sb-link:visited { color: inherit; }
a.sb-item.sb-link:hover { background: #1e293b; color: #fff; }
.sb-item .sb-ico { width: 22px; text-align: center; flex: none; }
/* Page links open in a new tab, so they must be visually distinguishable from
   the in-app nav buttons. Two cues, no extra markup:
   (a) a small ↗ marker, added by CSS only (an <a> has no child element to put
       it in, unlike the <button> items which must NOT get one), and
   (b) the hover title is set by the markup. */
a.sb-item.sb-link::after {
  content: "↗"; font-size: 11px; opacity: .55; margin-left: auto; padding-left: 6px;
}
.app-shell.sb-min .sidebar a.sb-item.sb-link::after { display: none; }
/* SVG/PNG icon replacements inside emoji slots: size to fit, no tint (assets
   ship their own colour), centre vertically next to the label. */
.sb-item .sb-ico,
.mb-tab .mb-ico,
.cs-act .cs-ico {
  display: inline-flex; align-items: center; justify-content: center;
}
.sb-item .sb-ico img,
.mb-tab .mb-ico img,
.cs-act .cs-ico img {
  width: 22px; height: 22px; object-fit: contain; display: block; flex: none;
}

.sidebar .sb-foot { padding: 12px; border-top: 1px solid #1e293b; }
/* Profile button shown above Logout in the sidebar footer. */
.sb-profile {
  display: flex; align-items: center; justify-content: flex-start; gap: 9px;
  width: 100%; padding: 9px 12px; margin-bottom: 8px; border-radius: 10px;
  background: #1e293b; color: #e2e8f0; border: none; cursor: pointer;
  font-size: 13px; font-weight: 600; text-align: start; transition: background .15s;
}
.sb-profile:hover { background: #334155; }
.sb-profile-email { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A WHITE disc behind the person, because the sidebar is dark: a bare glyph in
   the default black is invisible against #111a2e (it looked like an empty
   button). The disc also gives the icon a steady size whether an avatar image
   is used or the fallback glyph is. */
.sb-profile-icon {
  width: 26px; height: 26px; border-radius: 50%; background: #fff;
  color: #0f172a; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .28); overflow: hidden;
}
.sb-profile-icon svg { width: 17px; height: 17px; display: block; }
.sb-profile-icon img { width: 26px; height: 26px; object-fit: cover; display: block; }
/* Sidebar Logout: icon + label laid out nicely (only when shown, so the
   Tailwind .hidden state still fully hides it before login). */
#btnLogout:not(.hidden) { display: inline-flex; align-items: center; justify-content: flex-start; gap: 8px; }
#btnLogout.sb-foot-logout-danger,
.sb-foot #btnLogout { background: transparent; border-color: #334155; color: #cbd5e1; }
.sb-foot #btnLogout:hover { background: #dc2626; border-color: #dc2626; color: #fff; }
.sb-logout-lbl { white-space: nowrap; }
.sb-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: var(--r-pill); background: #1e293b; color: #94a3b8; }
.sb-badge.on { background: #064e3b; color: #6ee7b7; }

.app-main { flex: 1; margin-left: var(--sidebar-w); display: flex; flex-direction: column; min-width: 0; }

/* ---- RTL: the menu column moves to the RIGHT in Farsi ----------------------
   The sidebar is `position: fixed` with a hard-coded `left: 0`, and .app-main
   reserves its space with `margin-left` — so in Farsi the menu stayed nailed to
   the LEFT of an RTL page and the content margin reserved empty space on the
   wrong side. Flipping both is what puts the menu where a Farsi reader expects
   it. `margin-right` on .app-main (not `margin-left: 0` alone) keeps the content
   clear of the column. */
[dir="rtl"] .sidebar { left: auto; right: 0; }
[dir="rtl"] .app-main { margin-left: 0; margin-right: var(--sidebar-w); }

/* The bar's height is published so a `position: sticky` panel inside a page can
   pin BELOW it instead of sliding under it (the Video Studio's branding preview
   learned this the hard way: at `top: 0` only its bottom half stayed visible).
   Keep the two values in step with the `height` below. */
:root { --st-topbar-h: 62px; }
.topbar {
  height: 62px; background: #fff; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; padding: 0 26px;
  position: sticky; top: 0; z-index: 40;
}
.topbar h1 { font-size: 18px; margin: 0; }
.topbar .tb-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ---- Phone header: menu · title · language · bell · feedback · avatar ----
   The title stays in normal flow immediately after the hamburger (it used to be
   absolutely centred in the bar, which read as detached from the menu). The
   language chip is back in the header beside the bell; the drawer copy is only a
   fallback and is no longer shown. Feedback sits between the bell and the face. */
@media (max-width: 600px) {
  :root { --st-topbar-h: 56px; }
  .topbar { height: 56px; padding: 0 10px; gap: 8px; }
  .topbar > div:first-child { flex: 1 1 auto; min-width: 0; gap: 6px !important; }
  .topbar .tb-actions { gap: 6px; flex-wrap: nowrap; flex: 0 0 auto; }
  .topbar .tb-actions #btnPortfolioHome { display: none !important; }
  /* Bell / Feedback / language become equal round icon chips. */
  .topbar .tb-actions .i18n-toggle,
  .topbar .tb-actions .pill-btn#btnBell,
  .topbar .tb-actions .pill-btn#btnFeedback {
    width: 40px; height: 40px; min-width: 40px; min-height: 40px;
    padding: 0; gap: 0; border-radius: 50%; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .pill-btn#btnBell .tb-lbl, .pill-btn#btnFeedback .tb-lbl { display: none; }
  .pill-btn#btnBell .tb-ico, .pill-btn#btnFeedback .tb-ico { font-size: 20px; }
  .topbar .tb-avatar { width: 34px; height: 34px; }
  /* Normal flow, right beside the hamburger; one line, ellipsised. */
  .topbar h1 {
    position: static; inset: auto; transform: none;
    max-width: none; min-width: 0; margin: 0; font-size: 16px; font-weight: 800;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    pointer-events: auto;
  }
  .topbar #hamburger { min-width: 40px; min-height: 40px; }
}

/* The drawer's language chip was the old phone location. The header owns it now;
   keep the element for old cached markup but never show it in the menu. */
.sb-lang-toggle { display: none !important; }

/* The pinned bottom nav (+Create) and the sidebar now provide Compose/Accounts,
   so drop the redundant top-right "＋ Compose" and "🔑 Accounts" header buttons. */
#btnQuickPost, #btnAccounts { display: none !important; }

/* ---- Collapsible sidebar (desktop icon rail) -------------------------------
   A topbar hamburger (visible on both desktop & mobile) collapses the desktop
   sidebar to a slim icon rail; mobile keeps its slide-in drawer. */
@media (min-width: 861px) {
  #hamburger { display: inline-flex !important; }
  /* rail: narrow sidebar, icons centered, text labels hidden */
  .app-shell.sb-min .sidebar { width: var(--sidebar-w-min); transition: width .2s ease; }
  .app-shell.sb-min .app-main { margin-left: var(--sidebar-w-min); transition: margin-left .2s ease; }
  /* The collapsed icon rail follows the sidebar: in Farsi the space it frees is on
     the RIGHT, so the RTL variant must reserve the narrow width there. */
  [dir="rtl"] .app-shell.sb-min .app-main { margin-left: 0; margin-right: var(--sidebar-w-min); }
  .app-shell.sb-min .sidebar .sb-brand { justify-content: center; padding: 18px 6px 14px; }
  .app-shell.sb-min .sidebar .sb-brand .brand-word { display: none; }
  /* Rail mode: shrink the lockup to the width of the rail instead of hiding it
     (it is the only branding left once the menu labels are gone). */
  .app-shell.sb-min .sidebar .sb-brand .brand-logo { height: auto; width: 100%; }
  .app-shell.sb-min .sidebar .sb-label { display: none; }
  .app-shell.sb-min .sidebar .sb-item { justify-content: center; padding: 11px 6px; }
  .app-shell.sb-min .sidebar .sb-item > span:not(.sb-ico) { display: none; }
  /* Minimised rail: the user footer shows the user ICON only… */
  .app-shell.sb-min .sidebar .sb-profile-email { display: none; }
  .app-shell.sb-min .sidebar .sb-profile { justify-content: center; padding: 9px 6px; }
  .app-shell.sb-min .sidebar .sb-profile-icon { display: inline-flex; flex: none; }
  /* Keep the disc whole in the rail: an avatar image must fill it, not sit in it
     as a smaller circle inside a white ring. */
  .app-shell.sb-min .sidebar .sb-profile-icon img { width: 26px; height: 26px; }
  /* …and Logout becomes an icon-only button using logout.svg. */
  .app-shell.sb-min .sidebar .sb-logout-lbl { display: none; }
  .app-shell.sb-min #btnLogout { justify-content: center; padding: 9px 6px; }
  .app-shell.sb-min .sb-foot { padding: 10px 8px; }
}

/* =========================================================================
   Admin Hub — one sidebar entry that opens a colour-coded card grid.
   Each card is a shortcut to an existing admin view (accent colour comes from
   the inline --hub-c custom property set per category in shell.js).
   ========================================================================= */
.hub-head { margin-bottom: 4px; }
.hub-toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 16px;
}
.hub-search { position: relative; flex: 1 1 240px; min-width: 200px; max-width: 420px; }
.hub-search-ico {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  font-size: 13px; color: var(--text-3); pointer-events: none;
}
.hub-search input {
  width: 100%; box-sizing: border-box; padding: 9px 12px 9px 32px;
  border: 1px solid var(--border); border-radius: 10px;
  font-size: 13px; font-family: inherit; background: var(--surface, #fff); color: var(--text);
}
.hub-search input:focus { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50); }
.hub-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.hub-chip {
  border: 1px solid var(--border); background: #fff; color: var(--text-2);
  padding: 7px 13px; border-radius: var(--r-pill); font-size: 12.5px; font-weight: 600;
  font-family: inherit; cursor: pointer; transition: all .15s; white-space: nowrap;
}
.hub-chip:hover { border-color: var(--brand-400); color: var(--brand-600); }
.hub-chip.active { background: var(--brand-600); border-color: var(--brand-600); color: #fff; }

.hub-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 14px;
}
.hub-card {
  position: relative; display: flex; flex-direction: column; gap: 10px;
  padding: 16px 16px 14px 18px; background: #fff; cursor: pointer;
  border: 1px solid var(--border); border-left: 4px solid var(--hub-c, var(--brand-500));
  border-radius: 14px; box-shadow: var(--shadow-sm);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.hub-card:hover, .hub-card:focus-visible {
  transform: translateY(-2px); outline: none;
  border-color: var(--hub-c, var(--brand-500));
  box-shadow: 0 12px 28px rgba(15,23,42,.12);
}
.hub-card-top { display: flex; align-items: center; gap: 12px; }
.hub-card-ico {
  flex: none; width: 46px; height: 46px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center; font-size: 23px;
  background: color-mix(in srgb, var(--hub-c, #6366f1) 12%, #fff);
}
.hub-card-txt { min-width: 0; }
.hub-card-title { font-weight: 800; font-size: 15px; color: var(--text, #0f172a); line-height: 1.25; }
.hub-card-sub { font-size: 12.5px; color: var(--text-3); margin-top: 3px; line-height: 1.35; }
.hub-card-stat {
  font-size: 13px; font-weight: 700; color: var(--hub-c, var(--brand-600));
  background: var(--surface-2, #f1f5f9); border-radius: 8px;
  padding: 7px 10px; min-height: 32px; display: flex; align-items: center;
}
.hub-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; }
.hub-cat-tag {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: 3px 8px; border-radius: var(--r-pill); white-space: nowrap;
}
.hub-open {
  font-size: 12.5px; font-weight: 700; color: var(--hub-c, var(--brand-600));
  white-space: nowrap; transition: transform .15s ease; display: inline-block;
}
.hub-card:hover .hub-open { transform: translateX(3px); }
.hub-empty {
  text-align: center; color: var(--text-3); font-size: 13.5px; padding: 32px 10px;
}

@media (max-width: 860px) {
  /* Single stacked column on phones/tablets. */
  .hub-grid { grid-template-columns: 1fr; }
  .hub-search { max-width: none; flex-basis: 100%; }
}
/* RTL: the accent border and the "Open →" nudge flip sides. */
[dir="rtl"] .hub-card { border-left: 1px solid var(--border); border-right: 4px solid var(--hub-c, var(--brand-500)); }

/* ---- Admin → Platforms: one card per platform ---------------------------- */
/* A platform used to be a single cramped flex row (toggles + a big purple
   "Connection guide" button + three unlabelled number boxes). Each platform is
   now its own card with a header, a 3-column grid of controls and a full-width
   "Characters per message" row, so the columns line up across every card. */
.pf-intro { font-size: 12.5px; color: var(--text-3); margin-bottom: 12px; line-height: 1.5; }
.pf-list { display: flex; flex-direction: column; gap: 14px; }
.pf-card {
  background: #fff; border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-sm); padding: 14px 16px 16px;
}
.pf-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.pf-ico {
  flex: none; width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2, #f1f5f9);
}
.pf-ico img { width: 22px; height: 22px; object-fit: contain; }
.pf-name { font-size: 15px; font-weight: 700; color: var(--text); }
.pf-badge {
  margin-inline-start: auto; font-size: 11.5px; font-weight: 700;
  padding: 3px 10px; border-radius: var(--r-pill);
  background: var(--surface-2, #f1f5f9); color: var(--text-3); white-space: nowrap;
}
.pf-badge.on { background: #e7f6ef; color: var(--success, #059669); }
.pf-grid {
  display: grid; gap: 12px 20px; align-items: start;
  grid-template-columns: minmax(150px, 1fr) minmax(180px, 1.2fr) auto;
}
.pf-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.pf-toggle { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-2); cursor: pointer; }
.pf-toggle input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--brand-600); }
.pf-comp { gap: 6px; flex-wrap: wrap; }
.pf-num {
  width: 78px; padding: 5px 8px; border: 1px solid var(--border); border-radius: 8px;
  font-size: 13px; font-family: inherit; color: var(--text); background: #fff;
}
.pf-num:focus { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50, #eef2ff); }
.pf-comp .pf-num { width: 64px; }
.pf-actions { display: flex; gap: 8px; justify-self: end; align-items: flex-start; }
.pf-iconbtn {
  width: 38px; height: 38px; border-radius: 10px; border: 1px solid var(--border);
  background: #fff; font-size: 17px; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .15s, background .15s, transform .12s;
}
.pf-iconbtn:hover:not(:disabled) { border-color: var(--brand-400); background: var(--surface); transform: translateY(-1px); }
.pf-iconbtn.active { border-color: var(--brand-500); background: var(--brand-50, #eef2ff); }
.pf-iconbtn:disabled { opacity: .5; cursor: progress; }
.pf-limits { grid-column: 1 / -1; border-top: 1px dashed var(--border); padding-top: 12px; }
.pf-limits-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.pf-limits-label { font-size: 12.5px; font-weight: 700; color: var(--text-2); white-space: nowrap; }
.pf-field { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-3); white-space: nowrap; }
.pf-inputwrap { position: relative; display: inline-flex; align-items: center; }
.pf-inputwrap .pf-num { width: 86px; padding-inline-end: 22px; }
.pf-inf { position: absolute; inset-inline-end: 8px; font-size: 15px; line-height: 1; color: var(--text-3); pointer-events: none; }
.pf-hint { font-size: 12px; color: var(--text-3); margin-top: 6px; line-height: 1.5; }
.pf-guide {
  grid-column: 1 / -1; margin-top: 4px; border: 1px solid var(--border);
  border-radius: 10px; padding: 12px; background: var(--surface-2, #f8fafc);
}
.pf-footer { display: flex; align-items: center; gap: 12px; margin-top: 16px; flex-wrap: wrap; }
.pf-status { font-size: 12.5px; color: var(--text-3); }

/* ---- Profile page tabs + Notification Settings ---- */
.pf-tabs {
  display: flex; gap: 6px; padding: 4px; margin-bottom: 16px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-2, #f8fafc); width: max-content; max-width: 100%;
}
.pf-tab {
  border: 0; background: transparent; color: var(--text-2); font: inherit;
  font-size: 13px; font-weight: 600; padding: 8px 16px; border-radius: 9px;
  cursor: pointer; white-space: nowrap;
}
.pf-tab:hover { color: var(--text); }
.pf-tab.on { background: var(--surface, #fff); color: var(--text); box-shadow: 0 1px 2px rgba(15, 23, 42, .08); }
.pf-tab:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }
.pf-panel[hidden] { display: none; }

.np-group + .np-group { margin-top: 18px; }
.np-group h3 {
  font-size: 12.5px; font-weight: 700; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .04em; margin: 0 0 8px;
}
.np-row { display: flex; align-items: center; gap: 16px; padding: 12px 0; border-top: 1px solid var(--border); }
.np-group h3 + .np-row { border-top: 0; }
.np-copy { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
.np-copy b { font-size: 13.5px; font-weight: 600; color: var(--text); }
.np-copy span { font-size: 12px; color: var(--text-3); line-height: 1.5; }
.np-switches { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.np-switch {
  position: relative; display: inline-flex; align-items: center; gap: 7px;
  cursor: pointer; font-size: 12.5px; color: var(--text-2); user-select: none;
}
.np-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.np-track {
  position: relative; width: 36px; height: 20px; border-radius: 999px;
  background: var(--border-strong, #cbd5e1); transition: background .15s ease; flex: 0 0 auto;
}
.np-track::after {
  content: ""; position: absolute; top: 2px; inset-inline-start: 2px;
  width: 16px; height: 16px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .25); transition: transform .15s ease;
}
.np-switch input:checked + .np-track { background: var(--brand-600, #4f46e5); }
.np-switch input:checked + .np-track::after { transform: translateX(16px); }
[dir="rtl"] .np-switch input:checked + .np-track::after { transform: translateX(-16px); }
.np-switch input:focus-visible + .np-track { outline: 2px solid var(--brand-500); outline-offset: 2px; }
.np-switch.is-disabled { opacity: .45; cursor: not-allowed; }
.np-note {
  border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
  background: var(--surface-2, #f8fafc); color: var(--text-2);
  font-size: 12.5px; margin-bottom: 14px;
}
.np-actions {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border);
}
@media (max-width: 640px) {
  .pf-tabs { width: 100%; }
  .pf-tab { flex: 1 1 0; text-align: center; }
  .np-row { flex-direction: column; align-items: stretch; gap: 10px; }
  .np-switches { justify-content: space-between; }
}

@media (max-width: 860px) {
  .pf-grid { grid-template-columns: 1fr; }
  .pf-actions { justify-self: start; }
  .pf-limits { border-top: none; padding-top: 0; }
}
[dir="rtl"] .hub-card:hover .hub-open { transform: translateX(-3px); }

/* =========================================================================
   Admin Hub -> Dependencies (one Update button per package + Update All)
   ========================================================================= */
.deps-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 0; }
.deps-pill {
  font-size: 12px; font-weight: 600; color: var(--text-2);
  background: var(--surface-2, #f1f5f9); border: 1px solid var(--border);
  border-radius: var(--r-pill); padding: 4px 11px; white-space: nowrap;
}
.deps-pill.ok { background: #ecfdf5; border-color: #a7f3d0; color: #047857; }
.deps-pill.warn { background: #fffbeb; border-color: #fde68a; color: #b45309; }
.deps-interp {
  font-size: 11px; color: var(--text-3); background: transparent;
  border: none; padding: 0; margin-left: auto; overflow-wrap: anywhere;
}
.deps-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 14px 0 16px; }
.deps-hint { font-size: 12px; color: var(--text-3); }
/* Opt-in auto-restart toggle that sits with the action buttons. */
.deps-auto {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: 12.5px; font-weight: 600; color: var(--text-2);
  border: 1px solid var(--border); border-radius: var(--r-pill);
  padding: 6px 12px; background: var(--surface, #fff); user-select: none;
}
.deps-auto:hover { border-color: var(--brand-400); color: var(--brand-600); }
.deps-auto input { accent-color: var(--brand-600); cursor: pointer; margin: 0; }

/* Manual restart banner — sits ABOVE the package list and only appears once
   something has actually changed. */
.deps-restart-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin: 14px 0 0; padding: 13px 16px;
  background: #fffbeb; border: 1px solid #fde68a; border-left: 4px solid #f59e0b;
  border-radius: 12px;
}
.deps-restart-banner.is-busy { background: #eff6ff; border-color: #bfdbfe; border-left-color: #3b82f6; }
.deps-restart-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.deps-restart-txt b { font-size: 13.5px; color: #92400e; }
.deps-restart-banner.is-busy .deps-restart-txt b { color: #1d4ed8; }
.deps-restart-txt span { font-size: 12.5px; color: var(--text-2); }
.deps-restart-what {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; color: #b45309; overflow-wrap: anywhere;
}
.deps-restart-note { font-size: 12px; color: #b91c1c; overflow-wrap: anywhere; }
.deps-restart-btn { white-space: nowrap; }
.deps-restart-btn[disabled] { opacity: .55; cursor: not-allowed; }
.deps-loading { color: var(--text-3); font-size: 13.5px; text-align: center; padding: 28px 10px; }

.deps-list { display: flex; flex-direction: column; gap: 10px; }
.deps-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 14px 16px; background: #fff; border: 1px solid var(--border);
  border-left: 4px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-sm);
}
.deps-row.is-outdated { border-left-color: #f59e0b; }
.deps-row-main { display: flex; align-items: flex-start; gap: 12px; min-width: 0; flex: 1 1 auto; }
.deps-row-ico {
  flex: none; width: 40px; height: 40px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center; font-size: 20px;
  background: var(--surface-2, #f1f5f9);
}
.deps-row-txt { min-width: 0; }
.deps-row-title {
  font-weight: 800; font-size: 14.5px; color: var(--text); line-height: 1.3;
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.deps-kind {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-3); background: var(--surface-2, #f1f5f9);
  border-radius: var(--r-pill); padding: 2px 7px;
}
.deps-tag {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: #b45309; background: #fffbeb; border: 1px solid #fde68a;
  border-radius: var(--r-pill); padding: 2px 7px;
}
.deps-row-why { font-size: 12.5px; color: var(--text-2); margin-top: 4px; line-height: 1.45; }
.deps-row-impact { font-size: 11.5px; color: var(--text-3); margin-top: 4px; }
.deps-ver { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 12px; flex-wrap: wrap; }
.deps-ver-inst { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text-2); }
.deps-ver-arrow { color: var(--text-3); }
.deps-ver-new { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-weight: 700; color: #b45309; }
.deps-err {
  margin-top: 7px; font-size: 12px; color: #b91c1c; background: #fef2f2;
  border: 1px solid #fecaca; border-radius: 8px; padding: 7px 10px; line-height: 1.45;
}
.deps-note {
  margin-top: 7px; font-size: 12px; color: #92400e; background: #fffbeb;
  border: 1px solid #fde68a; border-radius: 8px; padding: 7px 10px; line-height: 1.45;
  overflow-wrap: anywhere;
}
.deps-last { font-size: 11px; color: var(--text-3); margin: -2px 0 0 4px; }
.deps-row-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex: none; }
.deps-status {
  font-size: 11.5px; font-weight: 700; border-radius: var(--r-pill);
  padding: 3px 9px; white-space: nowrap; background: var(--surface-2, #f1f5f9); color: var(--text-2);
}
.deps-status.ok { background: #ecfdf5; color: #047857; }
.deps-status.warn { background: #fffbeb; color: #b45309; }
.deps-status.err { background: #fef2f2; color: #b91c1c; }
.deps-status.busy { background: #eff6ff; color: #1d4ed8; }
.deps-btn { white-space: nowrap; }
.deps-btn[disabled] { opacity: .55; cursor: not-allowed; }
/* Already at the latest version: clearly inert, not just faded. */
.deps-btn.is-done,
.deps-btn.is-done[disabled] {
  opacity: .5; background: var(--surface-2, #f1f5f9) !important;
  color: var(--text-3) !important; border-color: var(--border) !important;
  cursor: not-allowed; box-shadow: none;
}
.deps-out {
  margin: 0 0 8px; padding: 10px 12px; font-size: 11.5px; line-height: 1.5;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: #0f172a; color: #e2e8f0; border-radius: 10px;
  max-height: 260px; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere;
}

@media (max-width: 720px) {
  .deps-row { flex-direction: column; }
  .deps-row-side { flex-direction: row; align-items: center; justify-content: space-between; width: 100%; }
  .deps-interp { margin-left: 0; flex-basis: 100%; }
}
[dir="rtl"] .deps-row { border-left: 1px solid var(--border); border-right: 4px solid var(--border); }
[dir="rtl"] .deps-row.is-outdated { border-right-color: #f59e0b; }
[dir="rtl"] .deps-row-side { align-items: flex-start; }
[dir="rtl"] .deps-restart-banner { border-left: 1px solid #fde68a; border-right: 4px solid #f59e0b; }
[dir="rtl"] .deps-restart-banner.is-busy { border-right-color: #3b82f6; }


.plan-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px;
  font-size: 13px; border: 1px solid var(--border); background: #fff;
  border-radius: var(--r-md); padding: 14px 16px; margin-bottom: 20px;
  box-shadow: var(--shadow-sm);
}
.plan-strip span { display: flex; flex-direction: column; gap: 2px; color: var(--text-3); }
/* --- Plan / usage cards: an icon on the left, stacked content on the right --- */
.plan-strip .plan-tag,
.plan-strip .plan-meter-cell {
  flex-direction: row; align-items: center; gap: 9px;
  padding: 8px 11px; border-radius: var(--r-md); background: var(--surface-2);
  min-width: 0;
}
/* ------- card icon (uniform on every card) ------- */
.plan-strip .pc-ico {
  font-size: 19px; line-height: 1; flex: none; color: var(--brand-600);
}
/* ------- content group (label/value, or metric text + bar) ------- */
.plan-strip .pc-body {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px;
  justify-content: center; align-self: stretch;
}
/* --- Tier box: small "Plan" label above a large, prominent tier value ---
   Matches the neutral card background of the other plan cells. */
.plan-strip .plan-tag .pc-body { align-items: flex-start; }
.plan-strip .pt-label {
  font-size: 11px; font-weight: 700; letter-spacing: .3px;
  text-transform: uppercase; color: var(--text-3);
}
.plan-strip .pt-value {
  font-size: 22px; line-height: 1.05; font-weight: 800; letter-spacing: -.2px;
  color: var(--brand-600); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.plan-strip .plan-tag-value {
  font-size: 24px; line-height: 1; font-weight: 800; letter-spacing: -.3px;
  color: var(--brand-600); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* --- Metric cells (Sent / Accounts / Storage) --- */
.plan-strip .plan-meter-cell {
  font-size: 13px; font-weight: 600; color: var(--text-2);
}
.plan-strip .plan-meter-cell > .pc-body { justify-content: center; }
.plan-strip .plan-meter-cell .pc-ico { align-self: center; }
.plan-strip .storage-meter {
  width: 100%; height: 8px; border-radius: 999px; background: var(--surface-3, #e2e8f0);
  overflow: hidden; display: block;
}
.plan-strip .storage-meter > span {
  display: block; height: 100%; width: 0%; border-radius: 999px;
  background: var(--ok, #16a34a); transition: width .3s ease, background .3s ease;
}
.plan-strip .storage-meter > span.st-orange { background: #f59e0b; }
.plan-strip .storage-meter > span.st-red { background: #dc2626; }
.plan-strip .pill-btn-upgrade {
  grid-column: 1 / -1; justify-self: end; align-self: center;
  margin: 0; font-size: 13px; font-weight: 700;
}

.app-content { padding: 26px 26px 40px; max-width: 1320px; margin: 0 auto; width: 100%; }

/* ---- Cards ---------------------------------------------------------------- */
.card {
  background: #fff;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  margin-bottom: 16px;
}
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 15px 20px; font-weight: 700; font-size: 15px;
  background: #fff; border-bottom: 1px solid var(--border);
  text-align: start; color: var(--text);
}
.card-head:hover { background: var(--surface); }
.card-head .chev { transition: transform .15s ease; color: var(--text-3); }
.card-head.open .chev { transform: rotate(180deg); }
.card-body { padding: 18px 20px; }
.card-body.hidden-body { display: none; }
.hidden-body { display: none; }

/* ---- Buttons -------------------------------------------------------------- */
.btn-primary {
  background: var(--brand-600); color: #fff;
  padding: .65rem 1.1rem; border-radius: var(--r-pill); font-weight: 600;
  border: 1px solid transparent; transition: background .15s, box-shadow .15s, opacity .15s;
  box-shadow: var(--shadow-brand);
}
.btn-primary:hover:not(:disabled) { background: var(--brand-700); }
.btn-primary:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

.btn-secondary {
  background: #fff; color: var(--text); border: 1px solid var(--border-2);
  padding: .55rem 1rem; border-radius: var(--r-pill); font-weight: 600;
  transition: background .15s, border-color .15s;
}
.btn-secondary:hover:not(:disabled) { background: var(--brand-50); border-color: var(--brand-400); color: var(--brand-600); }
.btn-secondary:disabled { opacity: .45; }

/* "Delete the built files" on Admin → Marketing. Small and red on purpose: it is
   the only destructive control on that page, and it sits at the far end of the
   button row (`margin-inline-start: auto`) so it cannot be caught while reaching
   for Download. It always confirms before doing anything. */
.st-mk-del {
  margin-inline-start: auto;
  background: #fff; color: var(--danger, #dc2626);
  border: 1px solid var(--danger, #dc2626);
  padding: .4rem .8rem; font-size: .8rem; font-weight: 700;
  border-radius: var(--r-pill); cursor: pointer; white-space: nowrap;
  transition: background .15s, color .15s, opacity .15s;
}
.st-mk-del:hover:not(:disabled) { background: var(--danger, #dc2626); color: #fff; }
.st-mk-del:disabled { opacity: .45; cursor: not-allowed; }

.btn-mini {
  background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border);
  padding: .4rem .75rem; border-radius: var(--r-pill); font-size: .8rem; font-weight: 600;
  transition: background .15s, border-color .15s; cursor: pointer; white-space: nowrap;
}
.btn-mini:hover { background: var(--brand-50); border-color: var(--brand-300); color: var(--brand-600); }

.btn-ghost {
  background: transparent; color: var(--text-2); border: 1px solid var(--border-2);
  padding: .4rem .9rem; border-radius: var(--r-pill); font-size: .82rem; font-weight: 600;
  transition: background .15s, border-color .15s; cursor: pointer; white-space: nowrap;
}
.btn-ghost:hover { background: var(--brand-50); border-color: var(--brand-300); color: var(--brand-600); }

/* ===== Email system (admin Emailing + user Reports) =====
   Keep action buttons pill-shaped and never let a long status/error message
   beside them stretch or collapse the button into a circle/oval. */
#emailAdminRoot button.btn-primary,
#emailAdminRoot button.btn-secondary,
#emailAdminRoot button.btn-danger,
#emailAdminRoot .btn-mini,
#reportsBody button.btn-primary,
#reportsBody button.btn-secondary,
#reportsBody button.btn-danger,
#reportsBody .btn-mini {
  flex: 0 0 auto;
  min-width: 0;
  white-space: nowrap;
  width: auto;
}
#emailAdminRoot .row-actions,
#reportsBody .row-actions,
#emailAdminRoot div.flex.flex-wrap,
#reportsBody div.flex.flex-wrap {
  row-gap: .5rem;
}
/* Status messages: keep them small and let them wrap on their own line. */
#emailAdminRoot .email-status,
#reportsBody .email-status {
  max-width: 100%;
  overflow-wrap: break-word;
  line-height: 1.4;
  flex: 1 1 100%;
}

.pill-btn {
  font-size: .76rem; font-weight: 700; padding: .45rem 1rem; border-radius: var(--r-pill);
  border: 1px solid var(--brand-200); background: var(--brand-50); color: var(--brand-700);
  cursor: pointer; transition: all .15s; white-space: nowrap; box-shadow: 0 1px 2px rgba(0,0,0,.05);
}
.pill-btn:hover { background: var(--brand-100); border-color: var(--brand-300); }

/* Topbar Bell + Feedback: flex layout so a dedicated icon glyph can be shown
   alone on compact/mobile screens while the text label stays for desktop. */
.pill-btn#btnBell, .pill-btn#btnFeedback {
  display: inline-flex; align-items: center; gap: 6px;
}
.pill-btn#btnBell .tb-ico, .pill-btn#btnFeedback .tb-ico {
  font-size: 16px; line-height: 1; display: inline-flex;
}
/* Mobile: collapse the Bell + Feedback pills into small circular icon chips so
   they no longer crowd/overlap the page title + hamburger on narrow phones.
   The app applies a global min 44x44 touch-target to all <button>s on mobile,
   so we size the Bell, Feedback and language chips to an equal 44px round so
   the whole top-right cluster lines up as one tidy row. */
@media (max-width: 560px) {
  .topbar .tb-actions .i18n-toggle,
  .topbar .tb-actions .pill-btn#btnBell,
  .topbar .tb-actions .pill-btn#btnFeedback {
    width: 44px; height: 44px; min-width: 44px; min-height: 44px;
    padding: 0; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    gap: 0; flex: none;
  }
  .pill-btn#btnBell .tb-lbl, .pill-btn#btnFeedback .tb-lbl { display: none; }
  .pill-btn#btnBell .tb-ico, .pill-btn#btnFeedback .tb-ico { font-size: 20px; }
}

.fmt-btn {
  width: 2rem; height: 2rem; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: .6rem; background: #fff; color: var(--text);
  font-size: .95rem; cursor: pointer; transition: background .15s, border-color .15s;
}
.fmt-btn:hover { background: var(--brand-50); }
.fmt-btn.active { background: var(--brand-100); border-color: var(--brand-300); }

/* ---- Tabs ----------------------------------------------------------------- */
.tabs { display: flex; gap: .3rem; background: var(--surface-2); padding: .3rem; border-radius: var(--r-pill); }
.tab {
  flex: 1; padding: .5rem .9rem; border-radius: var(--r-pill); font-weight: 600;
  color: var(--text-2); background: transparent; border: none; cursor: pointer;
  transition: background .15s, color .15s;
}
.tab.active { background: #fff; color: var(--brand-600); box-shadow: var(--shadow-sm); }
.tab-panel { display: block; }
.tab-panel.hidden { display: none; }

/* ---- Media Library modal overlay ------------------------------------------- */
/* Visibility is toggled via the .hidden class; flex-centering applies only
   when the overlay is shown (do NOT put display:flex in the inline style,
   inline styles override .hidden and leave the dark backdrop stuck on screen). */
#mediaPanelOverlay { display: none; align-items: center; justify-content: center; }
#mediaPanelOverlay:not(.hidden) { display: flex; }

/* ---- Composer media-library picker grid --------------------------------------
   Give every tile a fixed square-ish thumbnail area so photo/video previews
   render on BOTH desktop and mobile (the inline HTML adds no width/height, so
   without this the media bleeds / the video shows no frame on mobiles). */
#mediaPanel .media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 10px;
}
#mediaPanel .media-tile img,
#mediaPanel .media-tile video { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-thumb {
  position: relative; width: 100%; height: 112px;
  background: var(--surface-2, #f1f5f9); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.media-thumb.img, .media-thumb.audio { height: 112px; }
.media-thumb.audio { font-size: 30px; }

/* The picker's sticky "Use selected" footer. It MUST paint above the tiles: a
   phone leaves a tapped tile in :hover, which reveals that tile's ✏️ 📂 🗑 action
   strip (inline z-index:3), and with no z-index of its own this sticky bar
   (DOM-later but z-index:auto) lost to them — the reported "the icons overlay the
   Use selected button on the mobile". The solid ground also hides the tiles that
   scroll underneath it. */
#mediaPanel .media-pick-bar {
  position: sticky; bottom: 0; z-index: 20;
  background: var(--surface, #fff);
  padding: 8px 0;
  border-top: 1px solid var(--border, #e2e8f0);
}

/* Selection is a CLASS, not an inline style, so it can be toggled on a tile that
   already exists. Rebuilding the grid on every click destroyed the <img> nodes
   and re-triggered lazy decoding — a visible flicker on desktop, and thumbnails
   that flickered on/off on a phone. */
#mediaPanel .media-tile.on { outline: 3px solid var(--brand-500, #6d5cff); outline-offset: -1px; }
#mediaPanel .media-row.on { background: var(--brand-50); }
@media (max-width: 420px) {
  #mediaPanel .media-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
  .media-thumb { height: 96px; }
  .media-thumb.img, .media-thumb.audio { height: 96px; }
}

/* ---- Phone: the LIST view must not squeeze the pictures out ----------------
   The list is a five-column table (thumb, Name, Size, Added, Deletes on). On a
   narrow panel the columns cannot all fit, so the table out-grew the card AND the
   auto layout collapsed the thumbnail column to ~15px — Tailwind's `img{max-width:
   100%}` then shrank each 44px thumbnail to a sliver, i.e. "I do not see the
   thumbnails on the mobile". Three rules fix it below 640px:
     1. the metadata columns are dropped (the row is thumb + name + actions);
     2. the thumbnail column and its 44px image are pinned, so they can never
        collapse again;
     3. the name/actions row may wrap, which is what lets the table fit the panel
        instead of overflowing it. */
#mediaPanel .media-list-table th:first-child,
#mediaPanel .media-list-table td:first-child { width: 52px; min-width: 52px; }
#mediaPanel .media-list-table td:first-child img {
  width: 44px; height: 44px; min-width: 44px; max-width: 44px;
}
@media (max-width: 640px) {
  #mediaPanel .media-list-table { width: 100%; }
  #mediaPanel .media-list-table th:nth-child(n+3),
  #mediaPanel .media-list-table td:nth-child(n+3) { display: none; }
  #mediaPanel .media-list-table td:nth-child(2) { min-width: 0; }
  #mediaPanel .media-list-table td:nth-child(2) > .flex { flex-wrap: wrap; }
  /* ...and the name may use the width the dropped columns freed. */
  #mediaPanel .media-list-table td .truncate { max-width: none !important; flex: 1 1 auto; min-width: 0; }
  #mediaPanel .media-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
}

/* ---- Inline "Edit Photo" (Quick Post composer) ----------------------------- */
.qpe-step-on { border-color: var(--brand-500, #6366f1) !important; color: var(--brand-700, #4f46e5) !important; background: var(--brand-50, #eef2ff) !important; }
.qpe-on { border-color: var(--brand-500, #6366f1) !important; background: var(--brand-50, #eef2ff) !important; color: var(--brand-700, #4f46e5) !important; }
.qpe-stage {
  position: relative; width: 100%; height: 260px; border-radius: 12px; overflow: hidden;
  background: repeating-conic-gradient(#eef2f7 0 25%, #ffffff 0 50%) 50%/22px 22px;
  border: 1px solid var(--border); display: flex; align-items: center; justify-content: center;
}
.qpe-stage img { max-width: 100%; max-height: 260px; object-fit: contain; transition: filter .12s linear; }
.qpe-section {
  border: 1px solid var(--border); border-radius: var(--r-md); background: #fafbff;
  padding: .55rem .6rem;
}
.qpe-section .section-title { font-size: .72rem; letter-spacing: .02em; color: var(--text-2); margin-bottom: .4rem; }
.qpe-slider { margin: .45rem 0; }
.qpe-slider > div { font-size: .85rem; color: var(--text-2); }
.qpe-slider input[type=range] { width: 100%; accent-color: var(--brand-500, #6d5cff); }
.qpe-slider-val { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--brand-600, #6d5cff); }

/* ---- Upload busy overlay (loading gif) ------------------------------------ */
.upload-busy {
  position: fixed; inset: 0; z-index: 9999; background: rgba(15,23,42,.55);
  display: none; align-items: center; justify-content: center; padding: 20px;
}
.upload-busy.show { display: flex; }
.upload-busy-box {
  background: #fff; padding: 30px 44px; border-radius: 16px;
  text-align: center; box-shadow: 0 20px 50px rgba(15,23,42,.3);
}
.upload-busy-box img { width: 64px; height: 64px; display: block; margin: 0 auto; }
.upload-busy-box p { margin: 12px 0 0; font-weight: 600; color: var(--text, #1e293b); }
.upload-busy-box p::after { content: "…"; }

/* ---- Upload progress overlay (file counter + bar) -------------------------
   Separate from .upload-busy above: that one is a bare "busy" gif reused by AI,
   watermark, export and project-load. This one is specifically for FILE UPLOADS
   and adds the two things users actually read while waiting — how many files are
   done, and a bar. The gif is kept (smaller) because a percentage alone can sit
   still for a long time while the server compresses/queues, which reads as a
   hang; the motion is what says "still working". */
.up-prog {
  position: fixed; inset: 0; z-index: 10000; background: rgba(15,23,42,.55);
  display: none; align-items: center; justify-content: center; padding: 20px;
}
.up-prog.show { display: flex; }
.up-prog-box {
  background: #fff; padding: 26px 34px; border-radius: 16px; min-width: 300px;
  max-width: min(92vw, 420px); text-align: center;
  box-shadow: 0 20px 50px rgba(15,23,42,.3);
}
.up-prog-box img.up-prog-gif {
  width: 44px; height: 44px; display: block; margin: 0 auto 4px;
}
.up-prog-count {
  margin: 6px 0 0; font-weight: 700; font-size: 1.05rem;
  color: var(--text, #1e293b); font-variant-numeric: tabular-nums;
}
.up-prog-msg {
  margin: 4px 0 0; font-size: .82rem; color: var(--text-2, #64748b);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; direction: ltr;
}
/* Persian/Arabic file names should read RTL. */
[dir="rtl"] .up-prog-msg { direction: rtl; }
.up-prog-track {
  margin: 14px 0 0; width: 100%; height: 8px; border-radius: 999px;
  background: var(--bg-2, #f1f5f9); overflow: hidden; position: relative;
}
.up-prog-fill {
  height: 100%; width: 0%; border-radius: 999px;
  background: linear-gradient(90deg, var(--brand-500, #6d5cff), #8b5cf6);
  transition: width .25s ease;
}
/* Indeterminate: when we genuinely cannot know the percentage (e.g. the final
   send request, where upload + job creation are one atomic call). An animated
   bar already signals liveness, so the gif is hidden in this state. */
.up-prog.is-indeterminate .up-prog-fill {
  width: 40%; transition: none; animation: upProgSlide 1.2s infinite ease-in-out;
}
.up-prog.is-indeterminate img.up-prog-gif { display: none; }
@keyframes upProgSlide { 0% { margin-inline-start: -40%; } 100% { margin-inline-start: 100%; } }
.up-prog-pct {
  margin: 8px 0 0; font-size: .78rem; font-weight: 700;
  color: var(--text-2, #64748b); font-variant-numeric: tabular-nums;
}
/* Cancel is OPT-IN (the overlay only shows it when the caller passed onCancel).
   It must look like a real, clickable escape hatch without competing with the
   progress bar, so: a quiet outline that turns red on hover. `[hidden]` is what
   show() toggles, and `display:inline-block` would otherwise defeat it. */
.up-prog-cancel {
  display: inline-block; margin: 16px 0 0; padding: .45rem .95rem;
  border: 1px solid var(--border-2, #e2e8f0); border-radius: 10px;
  background: #fff; color: var(--text-2, #475569);
  font-size: .82rem; font-weight: 700; cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.up-prog-cancel[hidden] { display: none; }
.up-prog-cancel:hover:not(:disabled) {
  background: #fef2f2; border-color: #fecaca; color: #b91c1c;
}
.up-prog-cancel:disabled { opacity: .6; cursor: default; }

/* ---- Inputs ---------------------------------------------------------------- */
.inp-c {
  width: 100%; border: 1px solid var(--border-2); border-radius: var(--r-md);
  padding: .55rem .7rem; font-size: .9rem; background: #fff; color: var(--text);
  /* Keep password-manager / Chrome autofilled fields white instead of flashing
     Chrome's default grey/blue fill. The background-color transition pins the
     white fill while the autofill is applied. */
  -webkit-box-shadow: 0 0 0 1000px #fff inset;
  -webkit-text-fill-color: var(--text);
  transition: border-color .15s, box-shadow .15s, background-color 5000s ease-in-out 0s;
}
.inp-c:focus { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-100); }
.inp-c:-webkit-autofill,
.inp-c:-webkit-autofill:hover,
.inp-c:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #fff inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
  transition: background-color 5000s ease-in-out 0s;
}

/* Red highlight for missing / invalid required auth fields (signup, etc.) */
.inp-err,
.inp-err.inp-c {
  border-color: #e74c3c !important;
  box-shadow: 0 0 0 3px rgba(231, 76, 60, .15) !important;
}


/* ---- Admin → Payments: on/off toggles & one-of-N radio choices ------------- */
/* NOTE: never put .inp-c on a checkbox/radio. Its `width:100%`, its padding and
   its `0 0 0 1000px #fff inset` shadow squeeze the control to an empty white
   square and paint over the accent fill + tick, so a ticked box looked
   identical to an unticked one. These classes are the safe replacement. */
.pay-bool {
  display: flex; gap: 10px; align-items: flex-start; cursor: pointer;
  border: 1px solid var(--border-2); border-radius: var(--r-md);
  background: #fff; padding: 10px 12px; margin: 0 0 10px;
  transition: border-color .15s, background-color .15s, box-shadow .15s;
}
.pay-bool:hover { border-color: var(--brand-400); }
.pay-bool.is-on {
  border-color: var(--brand-500); background: var(--brand-50);
  box-shadow: 0 0 0 3px var(--brand-100);
}
.pay-bool > input[type=checkbox] {
  flex: 0 0 auto; width: 18px; height: 18px; margin: 1px 0 0;
  accent-color: var(--brand-600); cursor: pointer;
}
.pay-bool-txt { flex: 1 1 auto; min-width: 0; }
.pay-bool-title { display: block; font-size: 13px; font-weight: 600; color: var(--text); }
.pay-bool-help { display: block; font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
/* Explicit On/Off pill so the state is readable even at a glance. */
.pay-state {
  flex: 0 0 auto; font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; border-radius: var(--r-pill); padding: 3px 10px;
  border: 1px solid var(--border-2); color: var(--text-3); background: #fff;
}
.pay-bool.is-on .pay-state {
  border-color: var(--brand-500); background: var(--brand-500); color: #fff;
}

.pay-choice {
  border: 1px solid var(--border-2); border-radius: var(--r-md);
  background: #fff; padding: 10px 12px; margin: 0 0 10px;
}
.pay-choice-title { display: block; font-size: 13px; font-weight: 600; color: var(--text); }
.pay-choice-help { display: block; font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
.pay-choice-opts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 9px; }
.pay-opt {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  border: 1px solid var(--border-2); border-radius: var(--r-pill);
  padding: 6px 14px 6px 11px; background: #fff; font-size: 12.5px;
  font-weight: 600; color: var(--text-2); user-select: none;
  transition: border-color .15s, background-color .15s, color .15s;
}
.pay-opt:hover { border-color: var(--brand-400); }
.pay-opt:has(input:checked) {
  border-color: var(--brand-500); background: var(--brand-50); color: var(--brand-700);
}
.pay-opt input[type=radio] {
  width: 15px; height: 15px; margin: 0; flex: 0 0 auto;
  accent-color: var(--brand-600); cursor: pointer;
}
.pay-opt-help { font-size: 11.5px; font-weight: 400; color: var(--text-3); }


/* ---- Drop zone -------------------------------------------------------------- */
.drop-zone {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .25rem; text-align: center; border: 2px dashed var(--border-2);
  border-radius: var(--r-lg); padding: 1.5rem 1rem; color: var(--text-2);
  transition: border-color .15s, background .15s;
}
.drop-zone:hover { border-color: var(--brand-400); background: var(--brand-50); cursor: pointer; }
.drop-zone.dragover { border-color: var(--brand-500); background: var(--brand-50); }

/* ---- Log box ---------------------------------------------------------------- */
.log-box {
  background: #0f172a; color: #e2e8f0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .75rem; line-height: 1.5; border-radius: var(--r-md);
  padding: .75rem; height: 12rem; overflow-y: auto; white-space: pre-wrap; word-break: break-word;
}
.log-box .ok-line { color: #34d399; }
.log-box .err-line { color: #f87171; }

/* ---- Activity page: Status & log + Last posted -------------------------------
   Stack vertically on phones; go side-by-side only once there is room. */
.activity-grid { display: grid; grid-template-columns: 1fr; gap: 18px; }
@media (min-width: 860px) { .activity-grid { grid-template-columns: 1fr 1fr; } }

/* ---- Accounts page: the two tabs (Link accounts | Smart Publishing) ----------
   Smart Publishing used to be a third card at the BOTTOM of the page, under the
   whole connected-accounts list. One strip, two panels.
   Deliberately NOT the composer's `.tab` class: app.js's global setupTabs()
   hides EVERY `.tab-panel` on the page, so sharing it would let the composer's
   tabs switch these panels off (and the reverse). */
.acc-tabs {
  display: flex; gap: .3rem; padding: .3rem; margin: 0 0 18px;
  background: var(--surface-2, #f1f5f9); border-radius: var(--r-pill, 999px);
}
.acc-tab {
  flex: 1 1 0; min-width: 0; font-family: inherit; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: .55rem .8rem; border: 0; border-radius: var(--r-pill, 999px);
  background: transparent; color: var(--text-2, #64748b);
  font-size: 13px; font-weight: 700; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background .15s, color .15s, box-shadow .15s;
}
.acc-tab:hover { color: var(--brand-600, #4f46e5); }
.acc-tab.active {
  background: #fff; color: var(--brand-600, #4f46e5);
  box-shadow: var(--shadow-sm, 0 1px 2px rgba(15, 23, 42, .08));
}
.acc-tab:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--brand-100, #e0e7ff); }
.acc-panel { display: block; }
/* `hidden` must win over the display above; a panel that is only visually gone
   would still be tabbed into and read out. */
.acc-panel[hidden] { display: none; }

/* ---- Account cards & badges ------------------------------------------------- */
.account-card {
  display: flex; align-items: center; gap: .7rem;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: .7rem .85rem;
  background: #fff; box-shadow: var(--shadow-sm);
}
.account-card .acc-badge {
  font-size: .6rem; font-weight: 700; text-transform: uppercase; letter-spacing: .02em;
  padding: .18rem .5rem; border-radius: var(--r-pill); white-space: nowrap;
}
.badge-telegram { background: #dbeafe; color: #1e40af; }
.badge-bale { background: #dbeafe; color: #1d4ed8; }
.badge-eitaa { background: #dcfce7; color: #15803d; }
.badge-rubika { background: #fef3c7; color: #b45309; }
.badge-youtube { background: #fee2e2; color: #b91c1c; }
.badge-aparat { background: #fce7f3; color: #be185d; }
.badge-wordpress { background: #e0eef6; color: #155e75; }
/* A Public Portfolio is a local destination, not a platform; the violet
   matches the portfolio accent used on its own pages. */
.badge-portfolio { background: #ede9fe; color: #5b21b6; }
/* Soroush Plus — its brand blue (#1b74bc); the red in its logo is reserved for
   the destructive/urgent accents elsewhere in the UI. */
.badge-soroush { background: #dbeafe; color: #1b74bc; }

/* account toggle rows in Send-to */
.acc-toggle {
  display: flex; align-items: center; gap: .6rem;
  border: 1px solid var(--border-2); border-radius: var(--r-md); padding: .6rem .8rem;
  background: #fff; cursor: pointer; transition: background .15s, border-color .15s;
}
.acc-toggle:hover { border-color: var(--brand-400); }
.acc-toggle.on { background: var(--brand-50); border-color: var(--brand-500); }
.acc-toggle .sig-dot { font-size: .8rem; }
.acc-toggle .acc-ico {
  width: 34px; height: 34px; flex: none; border-radius: 10px; background: var(--surface-2);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.acc-toggle .acc-ico img { width: 22px; height: 22px; object-fit: contain; }

/* Bulk row account picker: platform icon, selected = brand halo ring (no tick box) */
.bulk-acc {
  display: inline-flex; align-items: center; gap: 7px;
  border: 2px solid var(--border-2); border-radius: 999px;
  padding: 5px 11px 5px 6px; background: #fff; cursor: pointer;
  font-size: 12px; font-weight: 600; color: var(--text-2);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.bulk-acc img { width: 20px; height: 20px; object-fit: contain; border-radius: 50%; }
.bulk-acc .bulk-acc-name { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bulk-acc:hover { border-color: var(--brand-400); }
.bulk-acc.on {
  border-color: var(--brand-500);
  background: var(--brand-50);
  box-shadow: 0 0 0 3px var(--brand-100), 0 2px 8px rgba(79,70,229,.18);
}
/* Smart Publishing rule ROW: the same pill, used as a read-only label (source →
   destinations) rather than a control, so it must not look clickable. */
.bulk-acc.mirror-pill { cursor: default; }
.bulk-acc.mirror-pill:hover { border-color: var(--border-2); }

/* ---- Smart Publishing: searchable rule list ---------------------------------- */
.mirror-search-row { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; flex-wrap: wrap; }
.mirror-search {
  flex: 1; min-width: 180px; max-width: 320px; box-sizing: border-box;
  border: 1px solid var(--border-2); border-radius: 10px;
  padding: 7px 12px; font-size: 13px; font-family: inherit;
  color: var(--text); background: var(--surface, #fff);
}
.mirror-search:focus { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-100); }
.mirror-list { display: flex; flex-direction: column; gap: 8px; }
.mirror-flow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.mirror-flow .mirror-arrow { color: var(--text-3); font-weight: 700; padding: 0 2px; }
/* Right-to-left: the arrow must point the way the text flows (destination on the
   left), which a mirrored glyph cannot do on its own. */
[dir="rtl"] .mirror-flow .mirror-arrow { transform: scaleX(-1); }

/* ---- Schedule fields ---------------------------------------------------------- */
.schedule-field {
  display: flex; align-items: center; gap: .6rem;
  border: 1px solid var(--border-2); border-radius: var(--r-md); padding: .65rem .8rem; background: #fff;
}
.schedule-field .sf-icon { font-size: 1.4rem; }
.schedule-field .sf-label { display: block; font-size: .7rem; color: var(--text-3); font-weight: 600; text-transform: uppercase; }
.sf-input { border: none; outline: none; font-size: 1rem; font-weight: 600; color: var(--text); background: transparent; width: 100%; }
.schedule-field:focus-within { border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-100); }

/* ---- Scheduled / misc ---------------------------------------------------------- */
.sched-item { border: 1px solid var(--border); border-radius: var(--r-md); padding: .65rem .8rem; background: #fff; box-shadow: var(--shadow-sm); }
.sched-countdown { font-size: .8rem; font-weight: 600; color: var(--brand-600); font-variant-numeric: tabular-nums; }

/* ---- Scheduled posts card: one scannable row (2026-11-14) --------------------
   Reported: the SENT rows were fine but a pending one was not — its text was
   clipped to 40 characters beside a pill, the date had no label, and the whole
   thing read as a paragraph. Each row is now four stacked lines:
     title (2 lines) + state  /  calendar + date + countdown  /  channel chips  /
     the options.
   The left edge is COLOURED by state, so a list of ten rows can be read at a
   glance: brand = waiting, grey = sent, red = not sent. */
.sched-item.sched-v2 {
  display: flex; flex-direction: column; gap: 8px;
  padding: .7rem .85rem .6rem;
  border-inline-start: 3px solid var(--brand-600, #4f46e5);
}
.sched-item.sched-v2.is-sent { border-inline-start-color: var(--border-2, #cbd5e1); background: #f8fafc; }
.sched-item.sched-v2.is-failed { border-inline-start-color: var(--danger, #ef4444); background: #fff7f7; }
.sched-top { display: flex; align-items: flex-start; gap: 10px; }
.sched-title {
  flex: 1 1 auto; min-width: 0;
  font-size: 14px; font-weight: 600; line-height: 1.45; color: var(--text, #0f172a);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
}
.sched-badge {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 800; line-height: 1;
  padding: 5px 9px; border-radius: 999px;
  background: var(--brand-100, #eef2ff); color: var(--brand-700, #3730a3);
  white-space: nowrap;
}
.sched-item.is-sent .sched-badge { background: #e2e8f0; color: #475569; }
.sched-item.is-failed .sched-badge { background: #fee2e2; color: #b91c1c; }
.sched-badge .ic { width: 13px; height: 13px; }
.sched-when {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--text-2, #475569);
}
.sched-when > .ic { width: 14px; height: 14px; flex: none; opacity: .65; }
.sched-when .sched-time { font-weight: 600; font-variant-numeric: tabular-nums; }
.sched-item .sched-countdown {
  font-size: 12px; font-weight: 800; color: var(--brand-700, #4338ca);
  background: var(--brand-100, #eef2ff); border-radius: 999px; padding: 3px 9px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.sched-item .sched-countdown.is-due { background: #dcfce7; color: #15803d; }
.sched-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sched-chip {
  font-size: 11.5px; font-weight: 600; color: #475569; background: #f1f5f9;
  border-radius: 999px; padding: 3px 9px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sched-actions {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding-top: 9px; border-top: 1px dashed var(--border, #e2e8f0);
}
/* A phone gets two buttons per line instead of three squeezed ones. */
@media (max-width: 520px) {
  .sched-actions { gap: 6px; }
  .sched-actions .btn-mini { flex: 1 1 calc(50% - 6px); text-align: center; }
}

.attach-chip {
  display: flex; align-items: center; gap: .5rem;
  border: 1px solid var(--border); border-radius: var(--r-md); padding: .5rem .75rem; background: #fff;
}
/* Thumbnail preview in the composer attachment tray (photo/video). */
.attach-chip .attach-thumb {
  flex: none; width: 44px; height: 44px; border-radius: 6px; overflow: hidden;
  background: var(--surface-2, #f1f5f9); border: 1px solid var(--border);
}
.attach-chip .attach-thumb img,
.attach-chip .attach-thumb video { width: 100%; height: 100%; object-fit: cover; display: block; }
.attach-chip .kind-badge {
  font-size: .65rem; font-weight: 700; text-transform: uppercase;
  padding: .15rem .4rem; border-radius: var(--r-pill); background: var(--brand-100); color: var(--brand-700);
}

/* ---- Attachment upload state (background upload queue) -------------------------
   A file uploads as soon as it is SELECTED, so the chip has to say what is
   happening to it. The bar is thin and the label short on purpose: it sits in a
   row with the filename and must not push the ✕ away on a phone. */
.attach-up { display: flex; align-items: center; gap: .4rem; flex: none; }
.attach-up-bar {
  width: 54px; height: 4px; border-radius: var(--r-pill); overflow: hidden;
  background: var(--surface-2, #f1f5f9); border: 1px solid var(--border);
}
.attach-up-fill {
  height: 100%; width: 0%; border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--brand-500, #6366f1), var(--accent-500, #06b6d4));
  transition: width .18s linear;
}
.attach-up-bar.up-fail { background: #fee2e2; border-color: #fecaca; }
.attach-up-bar.up-fail .attach-up-fill { background: #dc2626; width: 100% !important; }
.attach-up-lbl { font-size: .68rem; font-weight: 700; color: var(--text-3); white-space: nowrap; }
.attach-up-lbl.up-ok { color: #059669; }
.attach-up-lbl.up-fail { color: #dc2626; }
.attach-up-retry {
  flex: none; font-size: .68rem; font-weight: 700; cursor: pointer; font-family: inherit;
  padding: .15rem .5rem; border-radius: var(--r-pill);
  border: 1px solid #fecaca; background: #fff1f2; color: #b91c1c;
}
.attach-chip-failed { border-color: #fecaca; background: #fff7f7; }

/* ---- Smart Publishing switch (Compose + Bulk) -------------------------------
   ON is the default: the ticked channels plus the ones the user's mirror rules
   copy to, merged and de-duplicated by the server. OFF sends to exactly what is
   ticked. The checkbox is the control; the track/thumb are its look. */
.smart-pub {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem .7rem;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface, #f8fafc);
  cursor: pointer; user-select: none;
}
.smart-pub input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.smart-pub-track {
  position: relative; flex: 0 0 40px; width: 40px; height: 22px;
  border-radius: 999px; background: #cbd5e1; transition: background .18s ease;
}
.smart-pub-thumb {
  position: absolute; top: 2px; inset-inline-start: 2px;
  width: 18px; height: 18px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .32);
  transition: transform .18s ease;
}
.smart-pub input:checked + .smart-pub-track { background: var(--brand-600, #2563eb); }
.smart-pub input:checked + .smart-pub-track .smart-pub-thumb { transform: translateX(18px); }
[dir="rtl"] .smart-pub input:checked + .smart-pub-track .smart-pub-thumb { transform: translateX(-18px); }
.smart-pub input:focus-visible + .smart-pub-track { box-shadow: 0 0 0 3px rgba(37, 99, 235, .35); }
.smart-pub-txt { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.smart-pub-txt b { font-size: .8rem; color: var(--text-1); }
.smart-pub-txt small { font-size: .7rem; color: var(--text-3); }
.smart-pub.is-locked { opacity: .62; cursor: not-allowed; }
.smart-pub.is-locked .smart-pub-txt small { color: #b45309; font-weight: 700; }
/* The same switch, inside a Smart Publishing RULE row: no box of its own, it sits
   on the row next to Edit. The track/thumb geometry is untouched so the off/on
   travel is identical to Compose's. */
.smart-pub.mirror-act {
  flex: 0 0 auto; padding: 3px; border: 0; background: transparent; gap: 0;
}
.smart-pub.mirror-act:hover .smart-pub-track { box-shadow: 0 0 0 3px var(--brand-100, #e0e7ff); }
/* Phone: a rule's source → destination pills are wider than the card, so the
   switch used to sit ON TOP of them (and of Edit). Give the flow a full-width
   line of its own and put the actions underneath, right-aligned, with the
   switch first. Desktop is unchanged: one compact row. */
@media (max-width: 640px) {
  .account-card.mirror-rule-card {
    flex-wrap: wrap;
    align-items: center;
    row-gap: 8px;
  }
  .account-card.mirror-rule-card > .mirror-rule-info {
    flex: 1 1 100%;
    min-width: 0;
  }
  .account-card.mirror-rule-card > .mirror-act {
    margin-inline-start: auto;
  }
}

/* ---- Compose send footer: delivery options + actions ------------------------
   ONE panel holds the two send settings, each row with the SAME geometry and its
   switch on the SAME (inline-end) side. Before this, Smart Publishing put its
   switch on the left while Translations put its switch on the right, and the
   per-channel summary floated above both, detached from the switch it describes,
   so the block read as three unrelated widgets. Order inside the panel is the
   order the decision is made: DESTINATIONS (Smart Publishing) then LANGUAGE
   (Translations + the per-channel line). */
.send-opts {
  margin-top: .75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--card-bg, #fff);
  overflow: hidden;
}
.send-opt {
  display: flex; align-items: center; gap: .7rem;
  padding: .65rem .8rem; margin: 0;
  background: transparent; border: 0; cursor: pointer;
  user-select: none; text-align: start;
}
/* A hairline between the two rows, never a box around each of them. */
.send-opt + .send-opt { border-top: 1px solid var(--border); }
.send-opt:hover { background: var(--surface, #f8fafc); }
/* The label column takes the free space; the switch is placed at the END of the
   row by order, whichever side that is in the current direction. */
.send-opt-txt { display: flex; flex-direction: column; gap: .1rem; min-width: 0; flex: 1 1 auto; order: 2; }
.send-opt-txt b,
.send-opt-title { font-size: .82rem; font-weight: 700; color: var(--text); line-height: 1.3; }
.send-opt-txt small,
.send-opt-hint { font-size: .7rem; color: var(--text-3); line-height: 1.35; }
.send-opt-hint { display: block; }

/* The Compose rows reuse `.smart-pub` for its track/thumb (and its :checked
   sibling rule), but the panel owns the border/background: a row, not a card. */
.send-opt.smart-pub {
  border: 0; border-radius: 0; background: transparent;
  padding: .65rem .8rem; gap: .7rem; flex-wrap: nowrap;
}
.send-opt.smart-pub .smart-pub-track { order: 3; }
.send-opt.smart-pub .smart-pub-txt { order: 2; flex: 1 1 auto; }

/* Translations is a <button role="switch">, not a checkbox, so it carries its own
   track/thumb — SAME 40x22 geometry and brand colour as the Smart Publishing one. */
.send-switch {
  position: relative; flex: 0 0 40px; width: 40px; height: 22px;
  /* The app-wide 44px touch-target rule applies to EVERY <button>; a switch is
     not a tap-button, so opt out explicitly or it renders as a 44x44 blob. */
  min-width: 40px; min-height: 22px;
  order: 3; border: 0; padding: 0; border-radius: 999px;
  background: #cbd5e1; cursor: pointer; transition: background .18s ease;
}
.send-switch[aria-checked="true"] { background: var(--brand-600, #2563eb); }
.send-switch:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(37, 99, 235, .35); }
/* A 40x22 control is hard to hit on a phone. The pseudo-element enlarges the
   CLICKABLE area to ~44px tall without changing the layout (the app-wide 44px
   minimum applies to ordinary buttons, not to a switch's track). */
.send-switch::after { content: ""; position: absolute; inset: -11px -8px; border-radius: 999px; }
.send-switch-thumb {
  position: absolute; top: 2px; inset-inline-start: 2px;
  width: 18px; height: 18px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .32);
  transition: inset-inline-start .18s ease;
}
.send-switch[aria-checked="true"] .send-switch-thumb { inset-inline-start: 20px; }
/* The per-channel summary is part of the LANGUAGE row: it sits under the switch
   it describes, on its own line inside the same hairline-delimited block. */
.send-opt-lang { flex-wrap: wrap; }
.send-opt-sub { flex: 1 1 100%; order: 4; min-width: 0; }
.send-opt-lang.is-off .send-opt-title { color: #b45309; }
.send-opt-lang.is-off .send-opt-hint { color: #b45309; font-weight: 600; }
/* The compact "Language per channel … Change ›" line. DASHED top rule: it is a
   sub-line of the language row, not a second panel. */
.perlang-line {
  display: flex; align-items: center; gap: .5rem;
  width: 100%; margin: 0; text-align: start; cursor: pointer;
  border: 0; border-top: 1px dashed var(--border);
  padding: .5rem 0 .1rem; background: none;
  font-family: inherit; color: inherit;
}
.perlang-line:hover span:last-child { color: var(--brand-600); }

/* BOTH action buttons live on ONE side (the inline-end), one height, one radius,
   sharing the app's button theme. Schedule first in the markup and Send last, so
   the primary lands at the reading end; a phone turns the row into a column with
   Send on top. The old row stretched Send across the whole card and pinned
   Schedule to the opposite edge, with an emoji clock instead of the SVG icon. */
.send-actions {
  margin-top: 1rem;
  display: flex; align-items: center; justify-content: flex-end;
  gap: .55rem; flex-wrap: wrap;
}
.send-act {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .45rem; height: 46px; padding: 0 1.2rem; box-sizing: border-box;
  font-size: .95rem; font-weight: 700; line-height: 1; white-space: nowrap;
}
.send-act-primary { min-width: 15rem; padding: 0 1.6rem; font-size: 1rem; }
.send-act-ico { width: 17px; height: 17px; object-fit: contain; flex: none; }
@media (max-width: 640px) {
  .send-actions { flex-direction: column-reverse; align-items: stretch; }
  .send-act, .send-act-primary { width: 100%; min-width: 0; }
}

/* ---- Send queue (Composer) ----------------------------------------------------
   "Sending" is something you START. Pressing Send snapshots the message, clears
   the composer and continues in the background, so this strip is where that work
   reports back — one row per message, newest activity at the bottom. */
.sendq {
  display: flex; flex-direction: column; gap: .35rem;
  margin: .75rem 0 0; padding: .6rem .7rem;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface, #f8fafc);
}
/* Tailwind's .hidden is injected at runtime, so order is not guaranteed. */
.sendq.hidden, .send-pill.hidden { display: none !important; }
.sendq-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-3);
}
.sendq-clear {
  font-family: inherit; font-size: .68rem; font-weight: 700; cursor: pointer;
  border: none; background: none; color: var(--brand-600);
}
.sendq-row {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  font-size: .8rem; padding: .3rem .4rem; border-radius: .45rem; background: #fff;
  border: 1px solid var(--border);
}
.sendq-lbl { font-weight: 700; white-space: nowrap; }
.sendq-det { font-size: .72rem; color: var(--text-3); flex: 1 1 auto; min-width: 0; }
.sendq-bar { flex: 1 1 70px; min-width: 50px; height: 4px; border-radius: var(--r-pill); overflow: hidden; background: var(--surface-2, #f1f5f9); }
.sendq-fill {
  height: 100%; width: 0%; border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--brand-500, #6366f1), var(--accent-500, #06b6d4));
  transition: width .2s linear;
}
.sendq-sent { border-color: #bbf7d0; background: #f0fdf4; }
.sendq-failed, .sendq-held { border-color: #fecaca; background: #fff7f7; }
.sendq-held .sendq-lbl, .sendq-failed .sendq-lbl { color: #b91c1c; }
.sendq-cancelled { opacity: .6; }
/* The pill's click lands here — flash the strip so the eye finds it. */
.sendq-flash { animation: sendqflash 1.4s ease; }
@keyframes sendqflash {
  0%, 100% { box-shadow: none; }
  20%, 60% { box-shadow: 0 0 0 3px var(--brand-100, #e0e7ff); border-color: var(--brand-500, #6366f1); }
}

/* ---- Send pill (everywhere except the Composer) -------------------------------
   z-index 70 clears the mobile bottom nav (64). safe-area keeps it off the
   gesture bar on a phone.

   Reported twice: it "sits on top of the next button", "takes me away from my
   workflow" and "does not disappear after a few seconds". Two causes, both here
   and in paintSendPill(): the label was painted over the whole button, so there
   was nowhere for a ✕ to live, and a finished send is kept in state for five
   minutes, so the notice simply stayed. The label and the ✕ are now separate
   elements: the label is rewritten in place, the ✕ closes, and the pill's own
   click still opens the queue. */
.send-pill {
  position: fixed; z-index: 70;
  right: max(12px, env(safe-area-inset-right));
  bottom: calc(70px + env(safe-area-inset-bottom, 0px));
  font-family: inherit; font-size: .8rem; font-weight: 700; cursor: pointer;
  padding-block: .35rem; padding-inline: .85rem .4rem;
  border-radius: var(--r-pill); color: #fff;
  background: linear-gradient(135deg, var(--brand-600, #4f46e5), var(--accent-500, #06b6d4));
  border: 1px solid rgba(255, 255, 255, .25);
  box-shadow: 0 8px 22px rgba(15, 23, 42, .28);
  display: inline-flex; align-items: center; gap: .5rem;
}
.send-pill:hover { filter: brightness(1.06); }
.send-pill.pill-failed { background: linear-gradient(135deg, #dc2626, #b91c1c); }
.send-pill-txt { white-space: nowrap; }
/* The ✕. A 28px disc with a 44px touch target: the pill opens the queue when a tap
   lands anywhere else, so the ✕ has to be the easier thing to hit with a thumb. */
.send-pill-x {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  margin-block: -.35rem; margin-inline: 0 -.15rem;
  border-radius: 50%; background: rgba(255, 255, 255, .18);
  font-size: 13px; line-height: 1; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.send-pill-x::after { content: ""; position: absolute; inset: -8px; }
.send-pill-x:hover { background: rgba(255, 255, 255, .34); }
[dir="rtl"] .send-pill { right: auto; left: max(12px, env(safe-area-inset-left)); }

.send-retry-row { display: flex; align-items: center; gap: .5rem; border: 1px solid var(--border); border-radius: var(--r-md); padding: .5rem .6rem; }

.bulk-row { border: 1px solid var(--border); border-radius: var(--r-md); padding: .6rem; background: #fff; }
.bulk-row .row-status { font-size: .7rem; font-weight: 600; }
.bulk-row .row-status.ok { color: #059669; }
.bulk-row .row-status.fail { color: #dc2626; }
.bulk-row .row-status.pending { color: #94a3b8; }

/* ---- Auth modal (login/signup popup) ---------------------------------------------
   Added to #modalRoot (in app.js showAuthOverlay) while the auth popup is open.
   - Restores the brand indigo-tinted gradient backdrop (what the login screen
     used to look like) instead of the flat grey scrim used by other modals.
   - Top-anchors the card (align-items:flex-start) so switching between the
     shorter Log in form and the taller Sign up form does NOT make the popup
     re-center and jump vertically. Content grows downward from a fixed top. */
/* ---- Generic modal safety: sit above the mobile bottom nav -------------------
   The bottom nav bar uses z-index 64. Ensure the shared modal overlay always
   renders above it so its buttons (e.g. "Confirm send") are never hidden behind
   the sticky menu, and center the card on small screens. */
#modalRoot { z-index: 80; align-items: center; }
#modalRoot > #modalCard { border-radius: 16px; }
#modalRoot.auth-modal {
  /* Brand wash + the tinted mosaic as grain + the ink Tehran skyline along the
     bottom, so the login/register screen belongs to the landing page instead of
     being a flat scrim over a plain white card. Both decorations are absolutely
     positioned pseudo-elements on purpose: #modalRoot is a flex container, and an
     in-flow ::before would become a flex ITEM and shove the card around.
     NB the two artwork URLs carry no ?v= — a background written in CSS cannot take
     the template's asset_v (the stats strip does this with an inline style instead,
     see static/landing.css). */
  background:
    radial-gradient(900px 520px at 85% -12%, rgba(79,70,229,.18), transparent 60%),
    radial-gradient(760px 460px at 4% 104%, rgba(6,182,212,.16), transparent 55%),
    linear-gradient(135deg, #eef2ff 0%, #f8fafc 60%);
  align-items: flex-start;
  padding-top: 9vh;
  padding-bottom: 4vh;
  /* NOT `position: relative` — that overrode the overlay's `position: fixed` (the
     Tailwind `fixed inset-0` on #modalRoot) and collapsed the login screen to the
     height of its content, leaving the page's white background below it. A fixed
     element is already a containing block for these absolutely positioned layers. */
  overflow: hidden;
}
#modalRoot.auth-modal::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: url("/images/iran/brand/colours.svg") repeat;
  background-size: 300px auto;
  opacity: .06;
}
#modalRoot.auth-modal::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: min(42vh, 320px); pointer-events: none;
  /* `contain` and not `cover`: cover-cropping a skyline to a band slices the tower
     tops off (the lesson the hero learned), and this is a background so it cannot
     be given a natural height. */
  background: url("/images/iran/landscapedark.svg") no-repeat center bottom;
  background-size: contain;
  opacity: .14;
}
/* The card itself sits ABOVE both decorations. */
#modalRoot.auth-modal #modalCard { position: relative; z-index: 1; }
/* Auth card hero band: the logo sits on a brand wash with the hand-drawn swoosh
   behind it. The negative margins undo the card's own padding (p-5 = 20px) so the
   band bleeds to the card's edges, and the radius matches the card's rounded-2xl —
   without it the login card is a plain white sheet next to a decorated page. */
.auth-hero {
  position: relative; overflow: hidden; text-align: center;
  margin: -20px -20px 16px; padding: 20px 18px 16px;
  border-radius: 16px 16px 0 0;
  background: linear-gradient(180deg, #eef2ff 0%, rgba(255,255,255,0) 100%);
  border-bottom: 1px solid var(--border);
}
.auth-hero-art {
  position: absolute; left: 50%; top: 50%; width: 150%; max-width: none;
  transform: translate(-50%, -50%); opacity: .5; pointer-events: none;
}
.auth-hero .auth-home-link { position: relative; z-index: 1; }
#modalRoot.auth-modal #modalCard {
  box-shadow: 0 20px 50px rgba(15,23,42,.16);
  border: 1px solid var(--border);
}

/* ---- Language toggle on the auth/forgot modal (EN/FA) ----------------------- */
.auth-modal .lang-toggle {
  position: absolute;
  top: -0.25rem;
  right: 0;
  width: 2.1rem;
  height: 2.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  /* A step stronger than --border: the button now sits ON the card's tinted band
     (#eef2ff), where the old #e2e8f0 outline all but disappeared. */
  border: 1px solid var(--brand-200, #c7d2fe);
  background: #fff;
  color: var(--text-2, #475569);
  font-weight: 700;
  font-size: 0.95rem;
  cursor: pointer;
  transition: all .15s;
  box-shadow: 0 1px 3px rgba(15,23,42,.08);
  /* ABOVE the .auth-hero band below it. The toggle sits in the top corner, which is
     exactly where the hero's tinted band bleeds (its negative margin undoes the
     card's padding), and .auth-hero comes later in the DOM — so without a z-index it
     was painted UNDER that semi-transparent wash AND the hero swallowed the clicks:
     the button looked greyed out and dead, which is why the login page could not be
     switched to English. A positioned sibling with an explicit z-index paints (and
     hit-tests) above a z-index:auto sibling. */
  z-index: 2;
}
.auth-modal .lang-toggle:hover {
  border-color: var(--brand-500, #6366f1);
  color: var(--brand-600, #4f46e5);
}
[dir="rtl"] .auth-modal .lang-toggle { right: auto; left: 0; }

/* ---- Password action buttons (👁️ reveal / 🎲 generate) — square boxes ------
   Placed beside the password input with a small gap, as clean little boxes
   instead of half-pills fused to the field. */
.pw-action {
  flex: 0 0 auto;
  width: 2.4rem;
  height: 2.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border, #e2e8f0);
  background: #fff;
  color: var(--text-2, #475569);
  border-radius: .5rem;
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  padding: 0;
  transition: border-color .15s, color .15s, background .15s;
}
.pw-action:hover {
  background: #f8fafc;
  border-color: var(--brand-500, #6366f1);
  color: var(--brand-600, #4f46e5);
}


/* ---- Password requirements (signup + forgot password) ------------------------ */
.password-requirements { color: var(--text-2, #64748b); }
.password-requirements .req-item { transition: color .12s, opacity .12s; }
.password-requirements .req-item.passed { color: #16a34a; opacity: .85; }
.password-requirements .req-item.failed { color: #dc2626; }
.password-requirements .req-item:not(.passed):not(.failed) { opacity: .7; }

/* ---- Terms of Service / Privacy Policy agreement (signup step 1) -------------
   The tick that records consent, so it is given the weight a legal control
   deserves: a bordered box, a comfortable hit area, and text at readable size
   rather than the 11px footnote treatment it would get if it were styled like
   the password hints above it. `align-items: flex-start` keeps the box level
   with the FIRST line when the sentence wraps to two or three lines, which it
   does in both languages at mobile width. */
.auth-terms {
  display: flex; align-items: flex-start; gap: .6rem;
  padding: .7rem .8rem; margin-top: .25rem;
  border: 1px solid var(--border, #e2e8f0); border-radius: .65rem;
  background: var(--surface-2, #f8fafc);
  transition: border-color .15s, background .15s;
}
.auth-terms:hover { border-color: var(--brand-500, #6366f1); }
.auth-terms .auth-terms-cb {
  flex: 0 0 auto; width: 1.05rem; height: 1.05rem; margin-top: .15rem;
  accent-color: var(--brand-600, #4f46e5); cursor: pointer;
}
.auth-terms .auth-terms-txt { font-size: 13px; line-height: 1.55; color: var(--text-2, #475569); }
/* The two half-labels must stay clickable-but-inline: `display: inline` is what
   lets the before/link/after run together as one sentence. */
.auth-terms .auth-terms-txt label { display: inline; cursor: pointer; }
.auth-terms .auth-terms-link {
  color: var(--brand-600, #4f46e5); font-weight: 600;
  text-decoration: underline; text-underline-offset: 2px;
}
.auth-terms .auth-terms-link:hover { color: var(--brand-700, #4338ca); }
/* The error state reuses the auth fields' `.inp-err` class, so a missing tick
   looks like every other missing field instead of a second visual language. */
.auth-terms.inp-err { border-color: #f43f5e; background: #fff1f2; }
.auth-terms-note { font-size: 11.5px; color: var(--text-3, #94a3b8); margin: .35rem 0 0; line-height: 1.5; }

/* ---- Forgot-password method selection ---------------------------------------- */
#forgotMethods .method-option {
  display: flex; align-items: center; gap: .75rem; padding: .8rem 1rem;
  border: 2px solid var(--border, #e2e8f0); border-radius: .7rem; cursor: pointer;
  transition: border-color .15s, background .15s;
}
#forgotMethods .method-option.selected { border-color: var(--brand-600, #4f46e5); background: var(--brand-50, #eef2ff); }

/* ---- Toasts -------------------------------------------------------------------- */
.socials-toast {
  position: fixed; top: 14px; left: 50%; transform: translateX(-50%);
  color: #fff; font-size: 14px; padding: 10px 18px; border-radius: var(--r-pill);
  box-shadow: var(--shadow-lg); z-index: 100; animation: ss-toast-in .18s ease;
}
.socials-toast.ok { background: #16a34a; }
.socials-toast.err { background: #dc2626; }
.socials-toast.info { background: #4f46e5; }
@keyframes ss-toast-in { from { opacity: 0; transform: translate(-50%, -8px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* ---- Bottom-right notification pills ----------------------------------------
   THE one notification surface: every outcome (and every transient status) is
   a pill stacked in the bottom-right corner. A success is green and takes
   itself away after 10 s; an ERROR is red and stays until its X is pressed.
   Colours are the theme's own tokens, so the pill follows the app's palette
   instead of painting a hard-coded slab over it. z-index 900: above modals (80)
   and the old transient pill (100), below a full-screen editor (10000). */
.ss-pill-stack {
  position: fixed; right: 16px; bottom: 16px; z-index: 900;
  display: flex; flex-direction: column; gap: 10px; align-items: flex-end;
  max-width: min(400px, calc(100vw - 24px));
  pointer-events: none;
}
.ss-pill {
  pointer-events: auto; position: relative;
  display: flex; align-items: flex-start; gap: 9px;
  width: max-content; max-width: 100%; box-sizing: border-box;
  padding: 11px 42px 11px 14px;
  border: 1px solid var(--border, #e2e8f0);
  border-inline-start: 4px solid var(--border-2, #cbd5e1);
  border-radius: 14px;
  background: var(--surface, #fff);
  color: var(--text, #0f172a);
  box-shadow: var(--shadow-lg, 0 12px 32px rgba(15, 23, 42, .2));
  opacity: 0; transform: translateY(10px) scale(.98);
  transition: opacity .18s ease, transform .18s cubic-bezier(.2, .9, .3, 1.2);
}
.ss-pill-in { opacity: 1; transform: none; }
.ss-pill-out { opacity: 0; transform: translateY(8px) scale(.98); }
/* SUCCESS — green (the tick's colour), read in 10 s. */
.ss-pill-ok { border-inline-start-color: var(--success, #059669); background: var(--success-50, #ecfdf5); }
/* ERROR — red, and it does NOT go away by itself. */
.ss-pill-err { border-inline-start-color: var(--danger, #e11d48); background: var(--danger-50, #fff1f2); }
.ss-pill-info { border-inline-start-color: var(--brand-600, #4f46e5); background: var(--surface-2, #f1f5f9); }
.ss-pill::before {
  content: ""; flex: none; width: 9px; height: 9px; margin-top: 6px;
  border-radius: 50%; background: var(--border-2, #cbd5e1);
}
.ss-pill-ok::before { background: var(--success, #059669); }
.ss-pill-err::before { background: var(--danger, #e11d48); }
.ss-pill-info::before { background: var(--brand-600, #4f46e5); }
.ss-pill-body { min-width: 0; }
.ss-pill-title {
  margin: 0 0 2px; font-size: 11px; font-weight: 800;
  letter-spacing: .05em; text-transform: uppercase; color: var(--text-3, #94a3b8);
}
.ss-pill-msg { margin: 0; font-size: 13.5px; font-weight: 700; line-height: 1.45; color: var(--text, #0f172a); }
.ss-pill-detail {
  margin: 4px 0 0; font-size: 12.5px; line-height: 1.5;
  color: var(--text-2, #475569); white-space: pre-wrap; word-break: break-word;
  overflow-wrap: anywhere; max-height: 32vh; overflow-y: auto;
}
.ss-pill-actions { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.ss-pill-btn {
  border: 1px solid var(--border, #e2e8f0); background: var(--surface, #fff);
  color: var(--text, #0f172a); border-radius: 999px; padding: 5px 12px;
  font: inherit; font-size: 12px; font-weight: 700; cursor: pointer;
}
.ss-pill-btn:hover { border-color: var(--brand-400, #818cf8); color: var(--brand-700, #4338ca); }
.ss-pill-btn-2 { background: transparent; }
.ss-pill-x {
  position: absolute; top: 6px; inset-inline-end: 6px;
  width: 26px; height: 26px; padding: 0; border: none; border-radius: 50%;
  background: transparent; color: var(--text-3, #94a3b8);
  font-family: inherit; font-size: 16px; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.ss-pill-x:hover { background: rgba(15, 23, 42, .07); color: var(--text, #0f172a); }
@media (max-width: 480px) {
  .ss-pill-stack { left: 10px; right: 10px; bottom: 10px; max-width: none; align-items: stretch; }
  .ss-pill { width: auto; }
}

/* ---- Notification dialog --------------------------------------------------------
   Replaces the red/green pills for anything that REPORTS AN OUTCOME. A pill
   disappears after 2.8 s whether or not it was read, which is fine for "Link
   copied" and wrong for "There is no SRT content to translate." — the user is
   left staring at an unchanged screen with no idea why. This is a real dialog:
   a tick or a cross, the reason in words, and an OK button, so the message
   cannot be missed and the user chooses when to carry on.

   z-index 200: above #modalRoot (80) and .socials-toast (100), below the Photo
   Editor's full-screen shell (10000) — a notification should sit on top of a
   form the user is filling in, but must not float over a dedicated full-screen
   editor. */
.notify-root {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(15, 23, 42, .55);
  animation: notify-fade .14s ease;
}
.notify-root.hidden { display: none; }
@keyframes notify-fade { from { opacity: 0; } to { opacity: 1; } }
.notify-card {
  width: 100%; max-width: 27rem; background: #fff;
  border-radius: 18px; padding: 24px 22px 18px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, .28);
  text-align: center;
  animation: notify-pop .18s cubic-bezier(.2, .9, .3, 1.2);
  position: relative;                /* anchors the ✕ */
}
/* The ✕. A message now takes itself away after 5 s, and this is how it is waved
   off in the meantime — so closing a message never means finding the OK button
   first. */
.notify-x {
  position: absolute; top: 8px; inset-inline-end: 8px;
  width: 32px; height: 32px; padding: 0;
  border: none; border-radius: 50%; cursor: pointer;
  background: #f1f5f9; color: #64748b;
  font-family: inherit; font-size: 17px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.notify-x:hover { background: #e2e8f0; color: #0f172a; }
/* The transient status pill (toast): same ✕ idea, sized for a pill. */
.ss-toast-x {
  border: none; background: transparent; color: inherit; opacity: .75;
  font-family: inherit; font-size: 15px; line-height: 1; cursor: pointer;
  padding: 0 2px; margin: 0 -2px 0 0;
}
.ss-toast-x:hover { opacity: 1; }
@keyframes notify-pop { from { opacity: 0; transform: scale(.94) translateY(8px); } to { opacity: 1; transform: none; } }
/* Drawn as SVG rather than an emoji: ✅/❌ render as a different picture on every
   platform, and the whole point of this dialog is that the symbol is unambiguous. */
.notify-icon { width: 58px; height: 58px; margin: 2px auto 14px; }
.notify-icon svg { display: block; width: 100%; height: 100%; }
.notify-title { font-size: 17px; font-weight: 800; color: var(--text, #0f172a); margin: 0 0 6px; }
.notify-msg { font-size: 14.5px; line-height: 1.55; color: var(--text-2, #334155); margin: 0; }
.notify-detail {
  margin: 12px 0 0; padding: 10px 12px; text-align: start;
  background: var(--surface-2, #f1f5f9); border: 1px solid var(--border, #e2e8f0);
  border-radius: 10px; font-size: 13px; line-height: 1.6; color: var(--text-2, #475569);
  white-space: pre-wrap; word-break: break-word;
}
.notify-detail a { color: var(--brand-600, #4f46e5); font-weight: 600; }
.notify-count { margin-top: 8px; font-size: 12px; color: var(--text-3, #94a3b8); }
.notify-foot { margin-top: 18px; display: flex; gap: 10px; justify-content: center; }
.notify-foot .btn { min-width: 8.5rem; justify-content: center; }
@media (max-width: 420px) {
  .notify-card { padding: 20px 16px 14px; border-radius: 16px; }
  .notify-foot .btn { width: 100%; }
}

/* ---- "Work in progress" overlay --------------------------------------------------
   Shown while TRANSCRIBING or TRANSLATING, which are the two Studio operations
   that can run for minutes. Before this the only sign of life was a button
   label, so a long transcript looked exactly like a hang. */
.work-root {
  position: fixed; inset: 0; z-index: 190;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(15, 23, 42, .5);
  animation: notify-fade .14s ease;
}
.work-root.hidden { display: none; }
.work-card {
  width: 100%; max-width: 25rem; background: #fff;
  border-radius: 18px; padding: 26px 22px 22px; text-align: center;
  box-shadow: 0 24px 60px rgba(15, 23, 42, .28);
  animation: notify-pop .18s cubic-bezier(.2, .9, .3, 1.2);
}
.work-gif { width: 84px; height: 84px; object-fit: contain; margin: 0 auto 12px; display: block; }
.work-title { font-size: 16.5px; font-weight: 800; color: var(--text, #0f172a); margin: 0 0 4px; }
.work-note { font-size: 13px; line-height: 1.5; color: var(--text-2, #475569); margin: 0; min-height: 2.6em; }
.work-track {
  margin-top: 16px; height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--surface-2, #e2e8f0);
}
.work-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, var(--brand-500, #6366f1), var(--accent-500, #06b6d4));
  transition: width .35s ease;
}
/* No denominator available (a single blocking request): a moving stripe, which
   says "working" without pretending to know how far along it is. */
.work-track.is-indeterminate .work-fill {
  width: 40%; transition: none;
  background: linear-gradient(90deg, transparent, var(--brand-500, #6366f1), var(--accent-500, #06b6d4), transparent);
  animation: work-slide 1.15s linear infinite;
}
@keyframes work-slide { from { transform: translateX(-110%); } to { transform: translateX(280%); } }
.work-meta {
  margin-top: 10px; display: flex; justify-content: space-between; gap: 10px;
  font-size: 12px; font-weight: 600; color: var(--text-3, #94a3b8);
}
.work-pct { font-variant-numeric: tabular-nums; color: var(--brand-600, #4f46e5); }

/* ---- Watermark position grid & colour control ----------------------------------- */
.position-cell {
  height: 2.1rem; border: 1px solid var(--border-2); border-radius: .6rem; cursor: pointer;
  color: var(--text-2); font-weight: 600; background: #fff; transition: all .12s;
}
.position-cell:hover { border-color: var(--brand-400); }
.position-cell.active { background: var(--brand-600); border-color: var(--brand-600); color: #fff; }

.color-control { display: flex; align-items: center; gap: .5rem; width: 100%; }
.color-control .color-swatch {
  width: 2rem; height: 2rem; border-radius: .5rem; border: 1px solid var(--border-2);
  cursor: pointer; flex-shrink: 0; transition: transform .1s;
}
.color-control .color-swatch:hover { transform: scale(1.05); }
.color-control .color-hex {
  flex: 1; min-width: 0; border: 1px solid var(--border-2); border-radius: var(--r-md);
  padding: .45rem .55rem; font-size: .85rem; font-variant-numeric: tabular-nums;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.color-control .color-hex:focus { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-100); }
.color-control .color-native {
  width: 2.4rem; height: 2rem; border: 1px solid var(--border-2); border-radius: .5rem;
  padding: 0; background: transparent; cursor: pointer; flex-shrink: 0;
}

/* ---- KPIs / dashboard overview (Phase 2) ------------------------------------ */
.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; }
/* The dashboard launchpad tiles. 2px and a mid-grey rather than the app's 1px
   hairline: these ten ARE the dashboard, and they have to read as ten buttons at
   a glance instead of as ten panels. `grid-auto-rows: 1fr` gives every row the
   height of the tallest tile, so all ten boxes are the SAME size at every width
   instead of one per row-height. */
.quick-actions { grid-auto-rows: 1fr; }
/* The row/icon layout is ALSO stated here, not only in the tile's inline style:
   anything that writes `el.style.display` on a tile (show/hide by plan) would
   otherwise drop the inline `display:flex` and the icon would jump on top of the
   label — which is exactly what happened to the plan-gated Watch Now tile. */
.quick-chip { border: 2px solid #cbd5e1 !important; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: row; align-items: center; }
.quick-chip:hover { box-shadow: 0 10px 26px rgba(79,70,229,.2); }
.quick-ico { box-shadow: inset 0 0 0 1px rgba(79,70,229,.08); }
.chip-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 11px; border-radius: var(--r-pill);
  font-size: 12px; font-weight: 600; white-space: nowrap;
  background: var(--brand-50); color: var(--brand-600);
}
@media (max-width: 700px) {
  .dash-grid, #dashboardView > div:last-child { grid-template-columns: 1fr !important; }
}
/* Dashboard launchpad: on phones show a dense 2-column quick-tile grid so a
   writer can reach Compose / Photo Studio / Video Studio in one glance. */
@media (max-width: 560px) {
  .quick-actions {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 10px !important;
  }
  .quick-actions .quick-chip {
    padding: 12px !important;
    min-height: 112px !important;
    gap: 8px !important;
  }
  /* The icon slot has to be BORDER-box: without it the 40px here was 40px of
     CONTENT plus the 10px padding, i.e. a 60px icon in a 157px tile — the label
     was left ~89px and read as one word per line, which looked like the icon had
     been put on top of the words. `font-size` sizes the emoji to the box it is
     actually in (the glyph inherits it — see dashAction in shell.js). */
  .quick-actions .quick-chip .quick-ico {
    width: 40px !important; height: 40px !important;
    box-sizing: border-box !important;
    padding: 7px !important;
    font-size: 24px !important;
  }
}

/* ---- account platform picker (icon cards) -------------------------------- */
.plat-field .mb-3, .plat-field { display: block; }
.plat-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
.plat-pick {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 6px; border: 1.5px solid var(--border-2); border-radius: var(--r-md);
  cursor: pointer; background: #fff; transition: border-color .15s, background .15s;
}
.plat-pick:hover { border-color: var(--brand-400); }
.plat-pick.selected { border-color: var(--brand-500); background: var(--brand-50); box-shadow: 0 0 0 3px var(--brand-100); }
.plat-pick img { width: 26px; height: 26px; object-fit: contain; }
.plat-pick .plat-pick-label { font-size: 12px; font-weight: 600; color: var(--text-2); }

/* ---- Platform connection guides ----------------------------------------------------
   Collapsible, context-aware "how to connect" panel shown next to each
   platform's connection form inside the Add/Edit account modal. The HTML body
   comes from the admin-editable platform_settings table. -------------------------- */
.platform-guide {
  background: var(--surface-2, #f1f5f9);
  border: 1px solid var(--border, #e2e8f0);
  border-radius: var(--r-md, 10px);
  padding: 12px 14px;
  margin: 0 0 12px;
  font-size: 13.5px;
  color: var(--text-2, #334155);
  line-height: 1.55;
}
.platform-guide h4 {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-1, #0f172a);
  display: flex;
  align-items: center;
  gap: 6px;
}
.platform-guide ol { margin: 0; padding: 0 0 0 18px; display: flex; flex-direction: column; gap: 4px; }
.platform-guide li { font-size: 13.5px; }
.platform-guide code {
  background: #fff;
  border: 1px solid var(--border, #e2e8f0);
  padding: 1px 6px;
  border-radius: 5px;
  font-size: 12.5px;
  color: var(--brand-600, #6366f1);
}
.platform-guide a { color: var(--brand-600, #6366f1); text-decoration: underline; }
.platform-guide .guide-tip,
.platform-guide .guide-warning {
  margin-top: 9px;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 13px;
}
.platform-guide .guide-tip {
  background: rgba(99, 102, 241, 0.08);
  border-left: 3px solid var(--brand-500, #6366f1);
  color: var(--text-2, #334155);
}
.platform-guide .guide-warning {
  background: rgba(239, 68, 68, 0.08);
  border-left: 3px solid var(--danger, #dc2626);
  color: var(--danger, #dc2626);
}
.platform-guide-empty { display: none; }
/* "+ Tips" toggler under the platform fields (shows/hides the connection guide) */
.platform-guide-help {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border, #e2e8f0);
}
.btn-guide-help {
  padding: 6px 14px; background: transparent;
  border: 1px solid var(--border, #e2e8f0); border-radius: 999px;
  font-size: 13px; font-weight: 600; color: var(--text-2, #334155);
  cursor: pointer; transition: all .15s; font-family: inherit;
}
.btn-guide-help:hover { background: var(--surface-2, #f1f5f9); border-color: var(--brand-400); }
.btn-guide-help.open { background: var(--brand-50, #eef2ff); border-color: var(--brand-500); color: var(--brand-600, #6366f1); }
.platform-guide.video-guide + .btn-guide-help { margin-top: 10px; }

/* ---- Floating "Tips" window ---------------------------------------------------
   The connection guide opens here instead of inline: a draggable, always-on-top
   panel the user can park anywhere and keep reading while they work through the
   steps in another tab/app. z-index sits above every modal (#modalRoot is z-80),
   the admin overlays (z-95) and the toasts (z-100). ---------------------------- */
.guide-win {
  position: fixed; left: auto; top: 88px; right: 24px;
  z-index: 130;
  display: none;               /* shown by openGuideWindow() */
  flex-direction: column;
  width: min(380px, calc(100vw - 24px));
  max-height: min(72vh, 560px);
  background: #fff;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, .28), 0 2px 8px rgba(15, 23, 42, .12);
  overflow: hidden;
}
.guide-win-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
  background: linear-gradient(135deg, var(--brand-600, #4f46e5), var(--brand-500, #6366f1));
  color: #fff;
  cursor: grab;
  touch-action: none;          /* drag must not scroll the page on touch */
  user-select: none;
}
.guide-win-head.dragging { cursor: grabbing; }
.guide-win-ico { font-size: 15px; line-height: 1; }
.guide-win-title {
  flex: 1; min-width: 0;
  font-size: 13.5px; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.guide-win-close {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  border: none; cursor: pointer; font-size: 13px; line-height: 1;
  background: rgba(255, 255, 255, .18); color: #fff; font-family: inherit;
}
.guide-win-close:hover { background: rgba(255, 255, 255, .32); }
.guide-win-body {
  padding: 12px 14px 4px;
  overflow-y: auto;
  flex: 1; min-height: 0;
  -webkit-overflow-scrolling: touch;
}
.guide-win-body .platform-guide { margin: 0 0 10px; }
.guide-win-foot {
  flex: none;
  padding: 8px 14px 10px;
  border-top: 1px solid var(--border, #e2e8f0);
  background: var(--surface, #f8fafc);
  font-size: 11.5px; color: var(--text-3, #64748b);
}
.guide-win-state { font-size: 13px; color: var(--text-3, #64748b); margin-bottom: 8px; }
.guide-win-retry {
  padding: 5px 14px; border: 1px solid var(--border, #e2e8f0);
  border-radius: 999px; background: var(--surface-2, #f1f5f9);
  color: var(--text-2, #334155); font-size: 12.5px; font-weight: 600;
  cursor: pointer; font-family: inherit;
}
.guide-win-retry:hover { border-color: var(--brand-400); background: #fff; }
.platform-guide-help .btn-guide-help { font-weight: 700; }

/* ---- Pricing / plan cards (matched to the landing front page) --------------------- */
.upg-section-head { text-align: center; max-width: 640px; margin: 0 auto 36px; }
.upg-section-head h2 { font-size: clamp(28px,4vw,38px); letter-spacing:-0.01em; margin: 0 0 14px; }
.upg-section-head p { color: var(--text-2); font-size: 16.5px; margin: 0 0 20px; }
.upg-section-head .chips { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; }
.upg-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 20px; max-width: 1140px; margin: 0 auto; }
.price-card { background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg); padding: 28px 24px; display: flex; flex-direction: column; gap: 16px; position: relative; box-shadow: var(--shadow-sm); }
.price-card.popular { border: 2px solid var(--brand-500); box-shadow: var(--shadow-brand); }
.popular-badge { position: absolute; top: -14px; left: 50%; transform: translateX(-50%); background: var(--brand-600); color: #fff; font-size: 12px; font-weight: 700; padding: 5px 14px; border-radius: var(--r-pill); }
.price-card .price-name { font-weight: 700; font-size: 17px; }
.price-card .price-amt { font-size: 40px; font-weight: 800; white-space: nowrap; }
.price-card .price-amt span { font-size: 16px; font-weight: 500; color: var(--text-3); }
.price-card ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.price-card ul li { display: flex; gap: 9px; align-items: flex-start; font-size: 14.5px; color: var(--text-2); }
.price-card ul li .tick { color: #16a34a; font-weight: 800; line-height: 1.2; }
.price-card .btn { margin-top: auto; }

/* ---- Admin pricing & tiers editor -------------------------------------------------- */
.tier-admin { width: 100%; min-width: 640px; border-collapse: collapse; table-layout: fixed; }
.tier-admin .cmp-wrap { overflow-x: auto; }
.tier-admin .row-label { white-space: nowrap; font-weight: 700; font-size: 14px; }
/* Keep every column on one line and give them room to breathe. */
.tier-admin th { white-space: nowrap; font-size: 12px; }
.tier-admin td, .tier-admin th { padding: 12px 9px; vertical-align: middle; }
/* Balanced, readable column widths so the table fits without cramping. */
.tier-admin th:nth-child(1), .tier-admin td:nth-child(1) { width: 74px; }
.tier-admin th:nth-child(2), .tier-admin td:nth-child(2) { width: 120px; }
.tier-admin th:nth-child(3), .tier-admin td:nth-child(3) { width: 108px; }
.tier-admin th:nth-child(4), .tier-admin td:nth-child(4) { width: 100px; }
.tier-admin th:nth-child(5), .tier-admin td:nth-child(5) { width: 90px; }
.tier-admin th:nth-child(6), .tier-admin td:nth-child(6) { width: auto; }
/* Medium separator line between each tier row. */
.tier-admin tbody tr { border-bottom: 2px solid var(--border-2); }
.tier-admin tbody tr:last-child { border-bottom: none; }
.tier-admin tbody tr:first-child { border-top: none; }
/* Features cell: a button with the selected-feature chips to its right. */
.tier-admin .tier-feat-wrap { display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 430px; }
.tier-admin .tier-feat-btn {
  white-space: nowrap; flex: none; padding: 5px 10px; font-size: 12.5px;
}
.tier-admin .tier-feat-chips { display: flex; flex-wrap: wrap; gap: 5px; min-width: 0; }
.tier-admin .tier-feat-chip { max-width: 100%; }
.tier-admin .tier-feat-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600;
  border: 1px solid; border-radius: var(--r-pill); padding: 3px 10px; white-space: nowrap;
}
.tier-admin .tier-feat-chip-check {
  font-style: normal; font-weight: 800; font-size: 11px; line-height: 1;
}
.tier-admin .tier-feat-chip-check::before { content: "✓"; }
.tier-admin .tier-feat-none { color: var(--text-3); font-size: 12.5px; white-space: nowrap; }
/* Feature picker modal body. */
.tier-feat-modal { min-width: 280px; }
.tier-feat-intro {
  margin: 0 0 12px; font-size: 12.5px; color: var(--text-3);
  text-transform: capitalize; font-weight: 600;
}
.tier-feat-actions { display: flex; gap: 10px; margin-top: 16px; }
/* Halo toggle rows (used inside the feature modal). */
.tier-feat-modal .feat-item {
  position: relative; display: flex; align-items: center; gap: 12px;
  font-size: 14px; color: var(--text-2); cursor: pointer; white-space: nowrap;
  padding: 8px 10px; border-radius: var(--r-md);
  transition: background .15s, box-shadow .15s;
}
.tier-feat-modal .feat-item + .feat-item { margin-top: 2px; }
.tier-feat-modal .feat-item:hover { background: var(--brand-50); }
.tier-feat-modal .feat-item .tier-feat {
  position: absolute; opacity: 0; width: 0; height: 0; margin: 0; pointer-events: none;
}
/* Halo indicator ring (mirrors .bulk-acc.on pattern) */
.tier-feat-modal .feat-halo {
  position: relative; flex: none; width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--border-2); background: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .15s, box-shadow .15s, background .15s, transform .15s;
}
.tier-feat-modal .feat-dot { width: 0; height: 0; border-radius: 50%; background: #fff; transition: all .15s; }
.tier-feat-modal .feat-item:hover .feat-halo { border-color: var(--brand-400); }
.tier-feat-modal .feat-item .tier-feat:focus-visible + .feat-halo { box-shadow: 0 0 0 3px var(--brand-100); }
.tier-feat-modal .feat-item .tier-feat:checked + .feat-halo {
  border-color: var(--brand-600); background: var(--brand-600);
  box-shadow: 0 0 0 3px var(--brand-100), 0 2px 8px rgba(79,70,229,.35);
  transform: scale(1.06);
}
.tier-feat-modal .feat-item .tier-feat:checked + .feat-halo .feat-dot {
  width: 8px; height: 8px; background: #fff;
}
.tier-feat-modal .feat-text { line-height: 1.2; }
.tier-feat-modal .feat-item .tier-feat:checked ~ .feat-text { color: var(--brand-700); font-weight: 600; }

/* ---- Mobile bottom tab bar ----------------------------------------------------------
   Shown only <= 860px (when the left sidebar collapses to an off-canvas drawer).
   Offers instant one-tap access to the highest-value destinations plus a central
   "+ Create" action that opens a Compose / Photo Studio / Video Studio quick sheet. */
.mobile-bottom-nav {
  display: none; /* desktop: never shown */
  flex: none;
}
@media (max-width: 860px) {
  .mobile-bottom-nav {
    display: block;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 64;
    background: rgba(255,255,255,.97);
    -webkit-backdrop-filter: saturate(140%) blur(8px); backdrop-filter: saturate(140%) blur(8px);
    border-top: 1px solid var(--border);
    box-shadow: 0 -6px 18px rgba(15,23,42,.06);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .mb-nav-wrap {
    display: grid;
    grid-template-columns: 1fr 1fr auto 1fr 1fr;
    align-items: stretch;
    max-width: 520px; margin: 0 auto;
  }
  .mb-tab {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; padding: 8px 2px 7px; border: none; background: transparent;
    font-size: 10.5px; font-weight: 600; color: var(--text-3); cursor: pointer;
    line-height: 1.1; transition: color .12s;
  }
  .mb-tab .mb-ico { font-size: 19px; line-height: 1; }
  .mb-tab.active { color: var(--brand-600); }
  /* The PUBLIC PAGE tab (2026-11-05) is the only one that is not a view switch:
     it is an <a> to the public page, so it must lose the link defaults and be
     laid out exactly like the <button> tabs beside it. */
  a.mb-tab.mb-tab-page { text-decoration: none; }
  a.mb-tab.mb-tab-page:visited, a.mb-tab.mb-tab-page:hover { color: var(--text-3); }
  /* Its icon is the page's own profile picture, or the person glyph. A 22px
     disc keeps the same optical weight as the outline icons next to it, and the
     inset ring reads as a photo frame rather than a floating blob. */
  .mb-ico.mb-face {
    width: 22px; height: 22px; border-radius: 50%; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-2, #f1f5f9); color: var(--text-3);
    box-shadow: inset 0 0 0 1.5px rgba(15, 23, 42, .12);
  }
  /* The photo and the glyph are the SAME slot: exactly one is ever painted.
     The photo starts `display:none` in CSS (NOT a `hidden` class) and is only
     revealed by `.has-photo`, which the shell sets after the image has really
     LOADED — so a slow or 404 avatar can never flash the browser's broken-image
     icon on the tab bar.

     The selectors are written to THIS depth on purpose: the shared icon rule
     `.mb-tab .mb-ico img` (above) sets `display:block` at a higher specificity
     than a bare `.mb-face img` would, so anything shallower is silently beaten
     and the empty <img> shows its broken-image glyph. */
  .mb-tab .mb-ico.mb-face img {
    display: none; width: 100%; height: 100%; object-fit: cover;
  }
  .mb-tab .mb-ico.mb-face.has-photo img { display: block; }
  .mb-tab .mb-ico.mb-face .mb-face-fallback {
    width: 15px; height: 15px; display: block;
  }
  .mb-tab .mb-ico.mb-face.has-photo .mb-face-fallback { display: none; }
  .mb-create {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    border: none; cursor: pointer; background: transparent; padding: 4px 0 0;
  }
  .mb-create .mb-create-btn {
    width: 48px; height: 48px; margin-top: -18px; border-radius: 50%;
    border: 4px solid #fff; background: linear-gradient(135deg, var(--brand-500), var(--accent-500, #ec4899));
    color: #fff; font-size: 22px; line-height: 1; display: flex; align-items: center;
    justify-content: center; box-shadow: 0 6px 16px rgba(79,70,229,.35);
  }
  .mb-create:active .mb-create-btn { transform: scale(.95); }
  /* Keep page/layout clear of the fixed bottom bar */
  .app-content { padding-bottom: 96px; }

  /* Compose/Bulk: pin the primary Send/Schedule bar above the bottom nav so a
     mobile writer never has to scroll past accounts to post. Reuses the same
     #sendActions element (single ID, single handler) — desktop stays inline. */
  .app-shell .app-main #sendActions {
    position: fixed;
    left: 0; right: 0;
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    z-index: 50;
    margin: 0 !important;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    background: rgba(255,255,255,.97);
    -webkit-backdrop-filter: saturate(140%) blur(8px); backdrop-filter: saturate(140%) blur(8px);
    border-top: 1px solid var(--border);
    box-shadow: 0 -6px 18px rgba(15,23,42,.06);
  }
  /* Ensure the last account toggle is never hidden behind the pinned bar. */
  .app-shell .app-main #sendToBody { padding-bottom: 84px; }
  /* Studio step bars (Video .st-navbar / Photo .photos-navbar): lift them above
     the fixed bottom tab bar on phones so Previous/Next stay reachable. */
  .app-main .st-navbar,
  .app-main .photos-navbar {
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  }
}

/* "+ Create" quick-action sheet (mobile only) */
.create-sheet-veil {
  display: none; position: fixed; inset: 0; z-index: 70;
  background: rgba(15,23,42,.45);
}
/* The veil STOPS ABOVE the app's fixed bottom bar, and the sheet sits on top of
   that line. Covering the bar looked like "the sticky panel disappeared the
   moment I pressed +": the bar is exactly where the sheet is opened from, and
   hiding it took away the way back. (2026-11-12, asked directly.) Scoped to the
   phone breakpoint, because the bar only exists there. */
.create-sheet-veil.open { display: block; }
@media (max-width: 860px) {
  .create-sheet-veil.open {
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  }
}
.create-sheet {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-width: 520px; margin: 0 auto;
  background: #fff; border-radius: 18px;
  /* EIGHT tools are taller than a phone screen, and a box pinned to `bottom:0`
     with no cap grows UPWARDS out of the viewport: the title row (and its ×)
     left the screen entirely and the last button slid under the bar. Cap the
     sheet to the VEIL's height (the veil already ends above the bottom bar),
     scroll INSIDE it, and leave room after the last row, so the reader can move
     up to the × and down to the final button. `border-box` keeps the cap honest
     — content-box would add the padding back on top of it. */
  box-sizing: border-box;
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 8px 16px 14px;
  box-shadow: 0 -10px 40px rgba(15,23,42,.18);
}
/* The row is as tall as the 28px × button, not the 15px title, so a large
   bottom padding put a dead band under "Create" before the first card. Match
   the 8px card rhythm instead (asked 2026-11-13). */
.create-sheet .cs-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 15px; font-weight: 800; color: var(--text); padding: 6px 2px 8px;
}
.create-sheet .cs-act {
  display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 12px 14px; margin-bottom: 8px; border: 1px solid var(--border);
  border-radius: 14px; background: #fff; cursor: pointer; text-align: start;
  font: inherit; color: var(--text); transition: background .12s, border-color .12s;
}
.create-sheet .cs-act:active { background: var(--surface-2); border-color: var(--border-2); }
.create-sheet .cs-act .cs-ico {
  width: 42px; height: 42px; border-radius: 12px; flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 20px;
  background: var(--brand-50); color: var(--brand-600);
}
/* Menu-style SVG glyphs inside the Create sheet size bigger than the compact
   shared 22px slot so they read clearly in the 42px rounded icon chip. */
.create-sheet .cs-act .cs-ico img {
  width: 30px; height: 30px; object-fit: contain; display: block; flex: none;
}

/* ---- Media Library bulk action bar ---------------------------------------
   A floating bar that stays in view while the library is scrolled, so acting on a
   selection never means scrolling back to the top to find the buttons.

   `position: sticky` (not fixed) on purpose: it stays IN FLOW, so it cannot cover
   the last row of files the way a fixed bar would, and it needs no spacer element
   to reserve its height.

   Two structural rules make that work, both in shell.js:
     * the bar is a SIBLING of the panel card, inside `.media-bulk-host`. The card is
       `overflow: hidden` to clip its rounded corners, and a sticky child of an
       overflow-hidden box is positioned against a box that never scrolls — it would
       not move at all;
     * the host WRAPS the card as well as the bar, so the bar's containing block is
       taller than the bar. A sticky element can never move outside its containing
       block, so a host holding only the bar could not stick either.

   Layout: the selection PILL on the left, the actions pushed right. The pill is
   the one thing that changes as boxes are ticked, and "3" alone said nothing —
   it reads "3 images selected". */
.media-bulk-bar {
  position: sticky; bottom: 14px; z-index: 22;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 2px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 18px;
  background: rgba(255,255,255,.96);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
  backdrop-filter: saturate(160%) blur(10px);
  box-shadow: 0 14px 34px rgba(15,23,42,.18);
}
/* The markup sets `hidden` when nothing is ticked; a plain display:flex rule would
   override the browser's [hidden] { display: none }, which is how a "hidden" bar
   ends up on screen. */
.media-bulk-bar[hidden] { display: none; }
.media-sel-pill {
  flex: none; font-size: 12.5px; font-weight: 700; line-height: 1;
  padding: 8px 13px; border-radius: 999px; white-space: nowrap;
  color: var(--brand-700); background: var(--brand-50);
  border: 1px solid var(--brand-100);
}
.media-bulk-actions {
  display: flex; flex-wrap: wrap; gap: 8px;
  /* inline-start, not `left`: the actions belong at the END of the bar in BOTH
     directions, which is the right edge in English and the left edge in Farsi. The
     physical property happens to give the same result today, but it would break the
     moment the bar's own direction differed from the page's. */
  margin-left: auto;
  margin-inline-start: auto;
}
.media-bulk-actions .media-bulk-act {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  white-space: nowrap; min-height: 38px;
}
/* Phones: the words go, the icons stay — and each button keeps a 44px touch
   target. Sitting `bottom` above the fixed bottom tab bar (56px + its safe-area
   inset) is what stops the two bars from stacking on top of each other. */
@media (max-width: 640px) {
  .media-bulk-bar {
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    gap: 8px; padding: 8px; border-radius: 16px;
  }
  .media-bulk-act .mb-lbl { display: none; }
  .media-bulk-actions { gap: 6px; }
  .media-bulk-actions .media-bulk-act { min-width: 44px; min-height: 44px; font-size: 17px; padding: 0 10px; }
  .media-sel-pill { font-size: 11.5px; padding: 7px 11px; }
}
.create-sheet .cs-txt { flex: 1; min-width: 0; }
.create-sheet .cs-txt b { font-size: 14.5px; display: block; }
.create-sheet .cs-txt span { font-size: 12px; color: var(--text-3); }

/* ---- Responsive ------------------------------------------------------------------- */
/* Mobile: off-canvas drawer + a scrim to close it, and clearance so the
   drawer's Logout (and other bottom items) sit above the fixed bottom nav. */
.sidebar-scrim {
  display: none; position: fixed; inset: 0; z-index: 56;
  background: rgba(15,23,42,.4); backdrop-filter: blur(1px);
  -webkit-backdrop-filter: blur(1px);
}
@media (max-width: 860px) {
  .sidebar { transform: translateX(-100%); z-index: 62; }
  .sidebar.open { transform: translateX(0); z-index: 62; }
  .app-main { margin-left: 0; }
  /* RTL: the drawer is anchored to the RIGHT (see the [dir="rtl"] rule above), so
     it must slide in from that edge — translateX(-100%) would fling it further off
     the LEFT and out of view, leaving a menu that never appears. */
  [dir="rtl"] .sidebar { transform: translateX(100%); }
  [dir="rtl"] .sidebar.open { transform: translateX(0); }
  [dir="rtl"] .app-main { margin-right: 0; }
  /* Compact sides/top, but keep a generous bottom so content (lists, Logout,
     studio cards, "Clear All") always scrolls clear of the fixed bottom nav
     and the sticky studio step bars instead of being clipped underneath. */
  .app-content { padding: 18px 18px 120px; }
  .hamburger { display: inline-flex !important; z-index: 65; position: relative; }
  .sidebar.open ~ .sidebar-scrim { display: block; }
  /* Let the drawer's bottom actions scroll clear of the fixed bottom tab bar. */
  #sidebar .sb-foot {
    padding-bottom: calc(70px + env(safe-area-inset-bottom, 0px));
  }
  /* Extra safe cushion at the very bottom of tall scrollables so the last row
     of a Video Studio project grid / Photo selection is never covered. */
  .studio-grid, #photoEditorView .pe-grid { padding-bottom: 12px; }
  /* Dashboard: split "Upcoming scheduled posts" / "Recent activity" 50/50 on
     mobile (desktop keeps its 2/3–1/3 emphasis on upcoming). */
  .dash-bottom-grid { grid-template-columns: 1fr 1fr !important; }
}

/* ---- i18n / language toggle + RTL ------------------------------------------------ */
.i18n-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; padding: 0 8px; border: 1px solid var(--border-2);
  border-radius: var(--r-pill); background: #fff; cursor: pointer;
  font-size: 14px; font-weight: 700; color: var(--text-2);
  transition: all .15s; line-height: 1;
}
.i18n-toggle:hover { border-color: var(--brand-400); color: var(--brand-600); box-shadow: var(--shadow-sm); }

body.is-fa { letter-spacing: 0 !important; }
body.is-fa .price-amt, body.is-fa .kpi-row, body.is-fa .price-amt span { letter-spacing: 0 !important; }

[dir="rtl"] .plan-strip { flex-direction: row-reverse; }

/* =========================================================================
   Unified Inbox — premium two-panel design (Hootsuite/Buffer-inspired)
   ========================================================================= */
.skeleton {
  display: inline-block; border-radius: 6px;
  background: linear-gradient(90deg, #eef2f7 25%, #f6f8fb 37%, #eef2f7 63%);
  background-size: 400% 100%;
  animation: inbox-shimmer 1.2s ease infinite;
}
@keyframes inbox-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* Filter tabs (All / Open / Resolved) */
.inbox-tabs { display: flex; gap: 2px; }
.inbox-tab {
  position: relative; background: none; border: none; padding: 8px 6px 10px;
  font-size: 13px; font-weight: 600; color: var(--text-3); cursor: pointer;
  transition: color .12s; display: inline-flex; align-items: center; gap: 5px;
}
.inbox-tab:hover { color: var(--text-2); }
.inbox-tab.active { color: var(--brand-600); }
.inbox-tab.active::after {
  content: ""; position: absolute; left: 4px; right: 4px; bottom: -1px; height: 2px;
  background: var(--brand-600); border-radius: 2px;
}

/* Platform dot filters */
.inbox-plat {
  width: 28px; height: 28px; border-radius: 50%!important; border: 1px solid var(--border)!important;
  background: #fff!important; display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0; transition: all .12s;
}
.inbox-plat:hover { box-shadow: 0 0 0 2px var(--border-2); }
.inbox-plat.active { border-color: var(--brand-600)!important; box-shadow: 0 0 0 2px var(--brand-100); background: var(--brand-50)!important; }

/* Platform filter pills on the Accounts page (under "Connected Accounts") */
.acct-fplat {
  border: 1px solid var(--border); background: #fff; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
  border-radius: 999px; font-size: 13px; font-weight: 600; color: var(--text-2);
  font-family: inherit; transition: all .12s; line-height: 1;
}
.acct-fplat img { width: 16px; height: 16px; object-fit: contain; flex: none; }
.acct-fplat:hover { border-color: var(--border-2); box-shadow: 0 0 0 2px var(--border-2); }
.acct-fplat.active { border-color: var(--brand-600)!important; box-shadow: 0 0 0 2px var(--brand-100); background: var(--brand-50)!important; color: var(--brand-600)!important; }

/* =========================================================================
   Recurring (queues) view
   The queue card, its toolbar and each queue ROW. On desktop a row is a flex
   trio (icon · details · actions). On a phone the trio could not fit: the
   actions cluster kept its width, so the details were crushed into a narrow
   column beside five buttons that also spilled off the right edge. Below the
   breakpoint the row wraps and the actions take a full-width row of their
   own, so the details stay readable and every control is reachable.
   ========================================================================= */
.queue-card { padding: 0; overflow: hidden; }
.queue-head {
  padding: 18px 20px; display: flex; align-items: center;
  justify-content: space-between; flex-wrap: wrap; gap: 10px;
}
.queue-title { margin: 0; font-size: 18px; }
.queue-subtitle { color: var(--text-3); font-size: 13px; }
.queue-toolbar { gap: 10px; flex-wrap: wrap; align-items: center; padding: 0 20px 10px; }
.queue-search {
  flex: 1; min-width: 150px; max-width: 260px; margin-left: auto; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: 10px; padding: 7px 11px;
  font-size: 12.5px; background: var(--surface); font-family: inherit; color: var(--text);
}
.queue-search:focus { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px var(--brand-50); }
.queue-body { padding: 6px 20px 20px; min-height: 120px; }

.queue-row {
  display: flex; gap: 14px; align-items: flex-start;
  border: 1px solid var(--border); border-radius: 14px;
  padding: 16px; margin-bottom: 12px; background: #fff;
}
.queue-ico {
  width: 42px; height: 42px; border-radius: 12px;
  background: var(--brand-50); color: var(--brand-600);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; flex: none;
}
.queue-main { flex: 1; min-width: 0; }
.queue-name { font-weight: 700; }
.queue-meta { font-size: 13px; color: var(--text-2); margin-top: 4px; }
.queue-sub { font-size: 12.5px; color: var(--text-3); margin-top: 6px; }
.queue-actions {
  display: flex; gap: 6px; align-items: center;
  justify-content: flex-end; flex: none; flex-wrap: wrap;
}
.queue-chip { font-size: 11px; }

@media (max-width: 700px) {
  .queue-head { padding: 16px 14px; }
  .queue-toolbar { padding: 0 14px 12px; }
  .queue-body { padding: 4px 14px 16px; }
  /* The search takes the whole line instead of hugging the right edge next to
     wrapped filter pills. */
  .queue-search { flex: 1 1 100%; max-width: none; margin-left: 0; }
  .queue-row { flex-wrap: wrap; padding: 14px; }
  /* The actions drop BELOW the details (full width) instead of sharing the
     line, so the name/schedule text keeps the whole width and no button is
     cut off past the edge. */
  .queue-actions {
    flex: 1 1 100%; justify-content: flex-start;
    padding-top: 12px; margin-top: 2px; border-top: 1px dashed var(--border);
  }
  /* The buttons share each line edge to edge (two per line, the last one full
     width), instead of sitting at their natural size with a ragged edge. */
  .queue-actions .btn-mini { flex: 1 1 44%; min-height: 36px; padding: 8px 12px; }
}

/* Conversation list */
.inbox-2pane { height: calc(100vh - 230px); }
.inbox-2pane > .card { min-height: 0; }
.inbox-list { background: #fff; }
.inbox-row:hover { background: var(--surface-2); }
.inbox-row { position: relative; }
.inbox-row:hover .inbox-more { opacity: 1 !important; }

/* Thread bubbles area scaffold */
.inbox-thread { }
.inbox-thread > [data-thread-sticky] { position: sticky; top: 0; z-index: 5; background: #fff; }

/* Empty-state inner */
.inbox-empty-pad { padding: 48px 16px; }

/* Chat scrollbar (subtle) */
.inbox-list::-webkit-scrollbar, .inbox-thread::-webkit-scrollbar { width: 6px; }
.inbox-list::-webkit-scrollbar-thumb, .inbox-thread::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 999px; }

/* Responsive: tablet → list narrower; mobile → single column/tap-to-thread */
@media (min-width: 768px) and (max-width: 1024px) {
  .inbox-2pane { grid-template-columns: minmax(220px, 25%) minmax(0, 1fr) !important; }
}
@media (max-width: 767px) {
  .inbox-2pane { grid-template-columns: 1fr !important; }
  /* Left panel full width; right thread hidden until a conversation is tapped.
     On mobile we simply stack them (thread below) so nothing is lost. */
  .inbox-list-card { max-height: 46vh !important; }
}

/* RTL: flip bubble corners + alignment naturally via flex; ensure text-align */
[dir="rtl"] .inbox-row { text-align: right; }

[dir="rtl"] .quick-actions { direction: rtl; }

/* ---- Sticky red-circle close for modals / popups ------------------------- */
/* Makes the header (and its X close) stick to the top of the scrollable
   popup so it stays visible when the content is scrolled down. */
.modal-head {
  position: sticky;
  top: 0;
  z-index: 30;                 /* stays above the scrolling body */
  background: #fff;            /* opaque so body text scrolls beneath it */
  border-radius: 16px 16px 0 0;
}
/* The X close button: a red circle with a white cross */
.modal-close {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 28px; height: 28px; border: none; border-radius: 50%;
  background: #ef4444; color: #fff;
  font-size: 15px; font-weight: 700; line-height: 1; cursor: pointer;
  transition: background .15s, transform .15s;
  padding: 0;
}
.modal-close:hover { background: #dc2626; transform: scale(1.08); }
.modal-close:active { transform: scale(.96); }

/* ---- Admin Users list: hide the secondary "phone · joined · sent · tier"
   meta line on small screens so RTL rows stay tidy ------------------------ */
@media (max-width: 700px) {
  .au-meta { display: none !important; }
}

/* =========================================================================
   Pricing & Tiers admin — modern plan-card dashboard (dynamic tiers)
   ========================================================================= */
.btn-pill { border-radius: 999px !important; padding: 8px 18px !important; font-weight: 700 !important; }
.btn-pill small { font-weight: 500; opacity: .8; }

/* Row of plan cards + trailing "Add plan" tile */
.tcard-row {
  display: flex; gap: 16px; align-items: stretch;
  overflow-x: auto; padding: 6px 2px 16px;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
@media (min-width: 860px) {
  .tcard-row { flex-wrap: wrap; }
}
.tcard {
  flex: 0 0 auto; width: 280px; max-width: 92vw;
  min-height: 300px; scroll-snap-align: start;
  background: #fff; border: 1px solid var(--border);
  border-radius: 18px; padding: 16px 16px 14px;
  box-shadow: 0 1px 2px rgba(15,23,42,.05);
  display: flex; flex-direction: column; gap: 10px;
  transition: transform .14s ease, box-shadow .16s ease, opacity .15s ease;
  position: relative;
}
.tcard.dragging { opacity: .45; }
.tcard:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(15,23,42,.1); }
.tcard.muted { opacity: .55; }
.tcard-active { border-color: #1b74bc; box-shadow: 0 4px 16px rgba(27,116,188,.14); }
.tcard-free { border-color: #27ae60; }
.tcard.custom { border-style: dashed; }
.tcard .tcard-drag { position: absolute; top: 10px; left: 10px; cursor: grab; color: #cbd5e1; font-size: 14px; user-select: none; }
.tcard .tcard-badge-top { position: absolute; top: 10px; right: 10px; }
.tcard-popular-badge {
  display: inline-block; background: linear-gradient(135deg, #ffb347, #ff8c1a);
  color: #fff; font-size: 10.5px; font-weight: 800; letter-spacing: .2px;
  padding: 3px 9px; border-radius: 999px; box-shadow: 0 2px 6px rgba(255,140,26,.35);
}
.tcard .tcard-name { font-size: 17px; font-weight: 800; color: var(--text-1,#0f172a); display: flex; align-items: center; gap: 8px; }
.tcard .tcard-price { display: flex; align-items: baseline; gap: 6px; }
.tcard .tcard-price b { font-size: 26px; font-weight: 900; color: #1b74bc; letter-spacing: -.4px; }
.tcard .tcard-price small { color: var(--text-3); font-size: 12px; font-weight: 600; }
.tcard .tcard-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.tcard .tc-pill {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 700;
  padding: 4px 10px; border-radius: 999px; background: var(--surface-2,#f1f5f9);
  color: var(--text-2); border: 1px solid var(--border);
}
.tcard .tc-pill .em { font-size: 13px; }
.tcard-feats { margin-top: 2px; border-top: 1px dashed var(--border); padding-top: 8px; }
.tcard-feat {
  display: flex; align-items: center; gap: 9px; font-size: 12.5px; color: var(--text-2);
  padding: 3px 6px; border-radius: 7px; cursor: pointer; user-select: none;
}
.tcard-feat:hover { background: var(--surface); }
.tcard-feat .tmark { width: 17px; height: 17px; flex: none; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; font-size: 11px; font-weight: 800; }
.tcard-feat.on .tmark { background: #27ae60; color: #fff; }
.tcard-feat.off { color: #cbd5e1; }
.tcard-feat.off .tmark { background: #eef2f6; color: #c0c7d1; }
.tcard-foot { margin-top: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.tcard-foot .btn { flex: 1 1 auto; }
.tcard-add {
  flex: 0 0 auto; width: 200px; min-height: 300px; align-items: center; justify-content: center;
  border: 2px dashed var(--border-2); background: transparent; border-radius: 18px;
  color: var(--text-2); cursor: pointer; display: flex; flex-direction: column; gap: 8px;
  font-weight: 800; font-size: 15px; transition: all .15s;
}
.tcard-add:hover { border-color: #27ae60; color: #27ae60; background: rgba(39,174,96,.05); }
.tcard-add .plus { font-size: 30px; line-height: 1; }

/* Inline small number nudges on cards */
.tcard .tcard-bar .tc-big { font-weight:800; color: var(--text-1); }

/* Switch used on tier cards (kept inline for state, this adds polish) */
.tcard-sw {
  width: 44px; height: 24px; border-radius: 999px; border: none; display: inline-block;
  position: relative; cursor: pointer; vertical-align: middle; transition: background .15s;
}
.tcard-sw .knob { position: absolute; top: 2px; width: 20px; height: 20px; border-radius: 50%; background:#fff; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
.tcard-sw[data-on="1"] { background: linear-gradient(180deg,#22c55e,#16a34a); }
.tcard-sw[data-on="1"] .knob { right: 2px; }
.tcard-sw[data-on="0"] { background: #e2e8f0; }
.tcard-sw[data-on="0"] .knob { left: 2px; }

/* =========================================================================
   Admin Users — mobile-first card dashboard
   ========================================================================= */
.au-toolbar {
  position: sticky; top: 62px; z-index: 20;
  background: #f8fafc;
  padding: 10px 0 4px;
  display: flex; flex-direction: column; gap: 8px;
}
.au-toolbar-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.au-toolbar-main input#adminUsersSearch { flex: 1; min-width: 150px; }
.au-toolbar-main .spacer { flex: 1; }
.au-toolbar-filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.au-toolbar-filters .au-res-count { font-size: 12px; color: var(--text-3); margin-inline-start: auto; white-space: nowrap; }
.au-fsel { font-size: 13px; padding: 6px 9px; border: 1px solid var(--border); border-radius: 999px; background: #fff; color: var(--text-1); cursor: pointer; }

/* ---- multi-column sort button + its popover ------------------------------
   The panel is positioned by JS in VIEWPORT coordinates (position:fixed) and
   only its INSIDE is styled here: the filters row wraps, so the button can land
   at either edge and an `inset-inline-end` anchor would run off the screen. */
.au-sortbtn { display: inline-flex; align-items: center; gap: 6px; max-width: 240px; }
.au-sortbtn-i { font-size: 12px; flex: none; }
.au-sortbtn #adminUsersSortLabel { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-sortbtn.on { border-color: var(--brand-600, #4f46e5); color: var(--brand-600, #4f46e5); font-weight: 700; }
.au-sortpop { position: fixed; z-index: 90; background: #fff; border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 12px 32px rgba(15, 23, 42, .16); padding: 8px;
  font-size: 13px; overflow-y: auto; }
.au-sortpop-h { font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-3); padding: 3px 8px 2px; }
.au-sortpop-note { font-size: 11.5px; line-height: 1.45; color: var(--text-3); padding: 0 8px 7px; }
.au-sortpop-list { display: flex; flex-direction: column; gap: 2px; }
.au-sortrow { display: flex; align-items: center; gap: 6px; padding: 5px 8px; border-radius: 9px;
  background: var(--brand-50, #eef2ff); }
.au-sortadd { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-radius: 9px;
  background: none; border: none; font: inherit; color: var(--text-1); text-align: start; cursor: pointer; }
.au-sortadd:hover { background: #f1f5f9; }
.au-sortrank { flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--brand-600, #4f46e5);
  color: #fff; font-size: 11px; font-weight: 800; display: flex; align-items: center; justify-content: center; }
.au-sortrank.au-plus { background: #e2e8f0; color: var(--text-3); font-weight: 700; }
.au-sortname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-sortdef { flex: none; font-size: 12px; color: var(--text-3); }
.au-sortdir, .au-sortmv, .au-sortdel { flex: none; border: 1px solid var(--border); background: #fff;
  color: var(--text-2); border-radius: 7px; cursor: pointer; font-size: 11px; line-height: 1; padding: 3px 6px; }
.au-sortdir[aria-pressed="true"] { color: var(--brand-600, #4f46e5); border-color: var(--brand-600, #4f46e5); }
.au-sortmv:disabled { opacity: .35; cursor: default; }
.au-sortdel:hover { color: #b91c1c; border-color: rgba(185, 28, 28, .5); }
.au-sortpop-sep { height: 1px; background: var(--border); margin: 6px 4px; }
.au-sortpop-empty { font-size: 12px; color: var(--text-3); padding: 6px 8px; }
.au-sortpop-f { display: flex; justify-content: flex-end; padding: 6px 4px 2px; }
.au-sortreset { border: none; background: none; font: inherit; font-size: 12px; font-weight: 700;
  color: var(--brand-600, #4f46e5); padding: 4px 7px; border-radius: 7px; cursor: pointer; }
.au-sortreset:hover { background: var(--brand-50, #eef2ff); }

.au-grid {
  display: grid; gap: 12px;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .au-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (min-width: 1080px) { .au-grid { grid-template-columns: repeat(3, minmax(0,1fr)); } }
@media (min-width: 1500px) { .au-grid { grid-template-columns: repeat(4, minmax(0,1fr)); } }

.au-card {
  background: #fff; border: 1px solid var(--border); border-radius: 16px;
  padding: 14px; display: flex; flex-direction: column; gap: 10px;
  box-shadow: 0 1px 2px rgba(15,23,42,.04);
  transition: box-shadow .15s ease, transform .12s ease;
}
.au-card:hover { box-shadow: 0 8px 22px rgba(15,23,42,.10); transform: translateY(-1px); }
.au-card.suspended { opacity: .62; }
.au-card-top { display: flex; align-items: center; gap: 12px; }
.au-avatar {
  width: 44px; height: 44px; border-radius: 50%; flex: none;
  background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 17px; letter-spacing: .3px;
}
.au-id { }
.au-id .nm { font-weight: 800; font-size: 15px; color: var(--text-1,#2c3e50); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.au-id .em { font-size: 12.5px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-status { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; }
.au-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

/* ---- "logged in right now" ------------------------------------------------
   The headline count doubles as the filter: the pill above the toolbar shows how
   many sessions are live and toggles the list down to those users, so the figure
   an admin wants to act on IS the control that shows it. Same green as the
   Active dot, so "online" and "active" read as related but not identical. */
.au-online-bar { margin: 0 0 10px; }
.au-online-chip {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: 13px; font-weight: 700; color: var(--text-1);
  background: #fff; border: 1px solid var(--border); border-radius: 999px;
  padding: 6px 13px; cursor: pointer;
  transition: background .12s, border-color .12s, box-shadow .12s;
}
.au-online-chip b { font-variant-numeric: tabular-nums; font-size: 14px; }
.au-online-chip:hover { border-color: rgba(39,174,96,.6); background: #f2fbf5; }
.au-online-chip.on {
  color: #14663a; background: #e8f8ee; border-color: #27ae60;
  box-shadow: inset 0 0 0 1px rgba(39,174,96,.35);
}
/* The inline pill inside a row / card. Same shape as `.au-status` so a row does
   not grow a second kind of blob, but green-tinted so it is not mistaken for the
   Active/Suspended status next to it. */
.au-online {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 700; color: #14663a;
  background: #e8f8ee; border: 1px solid rgba(39,174,96,.35);
  border-radius: 999px; padding: 1px 8px; white-space: nowrap; margin-inline-start: 6px;
}
/* The list row was tuned to keep a whole user on one 60px line (see the
   `.au-row` note), and this pill is one more thing in that line, so it is trimmed
   there: same word, less padding. Below ~845px the row's own flex-wrap moves the
   actions to a second line — the designed degradation. */
.au-row .au-online { font-size: 10.5px; padding: 0 6px; margin-inline-start: 4px; gap: 4px; }
.au-stats { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12px; color: var(--text-2); }
.au-stats b { color: var(--text-1); }
.au-foot { display: flex; flex-wrap: wrap; gap: 6px; margin-top: auto; }
.au-foot .btn { flex: 1 1 auto; }

/* The two counters an admin scans for — ✉ messages sent and 📷 media processed.
   Drawn as inline SVG (not emoji) so they sit optically level with the label at
   any font size, and use the brand colour so each figure reads as one unit. */
.au-i { vertical-align: -2px; flex: none; }
.au-stat { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; color: var(--text-2); white-space: nowrap; }
.au-stat b { color: var(--text-1); font-variant-numeric: tabular-nums; }
.au-stat .au-i { color: #1b74bc; }
.au-stat-l { font-size: 11.5px; color: var(--text-3); }
.au-stats-counts { gap: 6px 18px; }
.au-stats-counts .au-stat { font-size: 13px; }

/* ---- how the list is laid out: card grid <-> one user per line ----------- */
.au-view {
  display: inline-flex; border: 1px solid var(--border); border-radius: 999px;
  overflow: hidden; background: #fff;
}
.au-view-btn {
  border: 0; background: transparent; color: var(--text-2); font: inherit;
  font-size: 13px; line-height: 1; padding: 6px 11px; cursor: pointer;
  transition: background .12s, color .12s;
}
.au-view-btn + .au-view-btn { border-inline-start: 1px solid var(--border); }
.au-view-btn:hover { background: var(--surface); color: #1b74bc; }
.au-view-btn.on { background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff; font-weight: 700; }

/* ---- list view: the same rows, stacked ----------------------------------- */
.au-list { display: flex; flex-direction: column; gap: 8px; }
.au-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--border); border-radius: 14px;
  padding: 10px 14px; box-shadow: 0 1px 2px rgba(15,23,42,.04);
  transition: box-shadow .15s ease, transform .12s ease;
}
.au-row:hover { box-shadow: 0 6px 18px rgba(15,23,42,.09); transform: translateY(-1px); }
.au-row.suspended { opacity: .62; }
.au-avatar-sm { width: 38px; height: 38px; font-size: 15px; }
.au-row-id { flex: 1 1 150px; min-width: 120px; }
.au-row-id .nm { font-weight: 800; font-size: 14px; color: var(--text-1); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.au-row-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.au-row-id .em { font-size: 12.5px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.au-row-status { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.au-row-stats { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
/* In the list the ICONS carry the meaning: the word labels would double the
   width of the two counters a scanner is reading, and there is a tooltip on each.
   The card view keeps them, where there is room to spell them out. */
.au-row .au-stat-l { display: none; }
.au-row-meta { display: flex; flex-direction: column; gap: 2px; font-size: 11.5px; color: var(--text-3); flex: 0 0 auto; min-width: 126px; }
.au-row-meta span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.au-row-acts { display: flex; align-items: center; gap: 6px; margin-inline-start: auto; }
/* Narrow: the line becomes two or three lines rather than squeezing the
   counters into an unreadable column. */
@media (max-width: 860px) {
  .au-row { align-items: flex-start; }
  .au-row-meta { flex-direction: row; gap: 12px; min-width: 0; }
  .au-row-acts { margin-inline-start: 0; }
}

/* Plan badge colors (Free gray / paid blue-purple / advanced gold / ent dark) */
.au-pill { font-size: 10.5px; font-weight: 800; border-radius: 999px; padding: 2px 9px; white-space: nowrap; }
/* The plan's expiry date, beside the badge. Red on purpose: a subscription about
   to lapse is the one thing on the row an admin should notice unprompted. Only
   drawn when the server sent a date, so a free plan shows the bare badge. */
.au-exp { color: #dc2626; font-size: 11px; font-weight: 800; white-space: nowrap; }

.au-pager { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.au-pager .p-btn {
  border: 1px solid var(--border); background: #fff; color: var(--text-2);
  border-radius: 8px; padding: 5px 11px; font-size: 13px; cursor: pointer;
}
.au-pager .p-btn.on { background: #1b74bc; color: #fff; border-color: #1b74bc; font-weight: 700; }
.au-pager .p-btn:disabled { opacity: .4; cursor: default; }

.autofab {
  position: fixed; right: 18px; bottom: 76px; z-index: 55;
  width: 54px; height: 54px; border-radius: 50%;
  background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff; border: none;
  font-size: 26px; line-height: 1; display: none; align-items: center; justify-content: center;
  box-shadow: 0 6px 18px rgba(27,116,188,.4); cursor: pointer;
}
@media (max-width: 700px) { .autofab { display: flex; } }

/* ---- Admin → Users → Companies shelf ------------------------------------- */
/* The tab strip is the existing `.pf-tabs` (same shape as Profile) with the
   users-card spacing. */
.au-tabs { margin: 0 0 14px; }
.au-tab-n { font-size: 11.5px; font-weight: 700; color: var(--text-3); margin-inline-start: 4px; }
.au-tab.on .au-tab-n { color: inherit; }
#auUsersPanel[hidden], #auCompaniesPanel[hidden] { display: none !important; }

/* The company marker on a user row/card. In the tight LIST row it is icon-only
   (the tooltip names the company and the role); the card has room for the name. */
.au-cochip {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid #bae6fd; background: #f0f9ff; color: #0369a1;
  border-radius: 999px; padding: 1px 7px; font: inherit; font-size: 11px;
  font-weight: 700; cursor: pointer; max-width: 150px; white-space: nowrap;
}
.au-cochip:hover { background: #e0f2fe; }
.au-cochip .au-i { color: #0369a1; }
.au-cochip-l { overflow: hidden; text-overflow: ellipsis; }

/* The directory table reuses `.co-table`, including its 640px card mode; these
   are only the cells that are specific to companies. */
.au-co-toolbar { margin-bottom: 4px; }
.au-co-table td { vertical-align: middle; }
.au-co-table .au-co-th-acts { width: 1%; white-space: nowrap; }
.au-co-table .au-co-acts { text-align: end; white-space: nowrap; }
.au-co-namebtn {
  display: flex; align-items: center; gap: 9px; text-align: start;
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: inherit; min-width: 0; max-width: 280px;
}
.au-co-namebtn b { display: block; font-size: 13.5px; }
.au-co-nametxt { min-width: 0; }
.au-co-logo {
  width: 34px; height: 34px; border-radius: 9px; object-fit: cover;
  flex: none; background: #eef2f6;
}
.au-co-logo-t {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800; color: #475569; letter-spacing: .02em;
}
.au-co-logo-big {
  width: 54px; height: 54px; border-radius: 13px; object-fit: cover;
  flex: none; background: #eef2f6;
}
.au-co-logo-big.au-co-logo-t { font-size: 18px; }
.au-co-sub { display: block; font-size: 11.5px; color: var(--text-3); margin-top: 2px; }
.au-co-muted { color: var(--text-3); font-size: 12px; }
.au-co-owner {
  border: 0; background: none; padding: 0; font: inherit; font-size: 13px;
  font-weight: 700; color: #1b74bc; cursor: pointer; text-align: start;
}
.au-co-owner:hover { text-decoration: underline; }
.au-co-site { font-size: 12.5px; color: #1b74bc; text-decoration: none; }
.au-co-site:hover { text-decoration: underline; }
.au-co-q {
  display: inline-block; font-size: 11px; font-weight: 700; border-radius: 999px;
  padding: 1px 7px; background: #fef3c7; color: #92400e; margin-inline-end: 4px;
}
.au-co-arrow { font-size: 10px; color: var(--text-3); margin-inline-start: 3px; }
.au-co-arrow.on { color: #1b74bc; }
.au-co-empty { text-align: center; color: var(--text-3); padding: 40px 10px; }

/* The company panel inside the wide modal. */
.au-co-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.au-co-headmain { flex: 1 1 220px; min-width: 0; }
.au-co-panelname { font-size: 17px; font-weight: 800; color: var(--text-1); }
.au-co-panelmeta { font-size: 12.5px; color: var(--text-2); margin-top: 3px; word-break: break-word; }
.au-co-panelmeta a { color: #1b74bc; text-decoration: none; }
.au-co-panelmeta a:hover { text-decoration: underline; }
.au-co-headactions { display: flex; gap: 6px; flex-wrap: wrap; }
.au-co-kpis {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px; margin: 4px 0 14px;
}
.au-co-kpi {
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px;
  background: var(--surface-2, #f8fafc); min-width: 0;
}
.au-co-kpi span { display: block; font-size: 10.5px; color: var(--text-3); text-transform: uppercase; letter-spacing: .03em; }
.au-co-kpi b { display: block; font-size: 16px; color: var(--text-1); margin-top: 2px; }
.au-co-sec { font-weight: 800; font-size: 13px; margin: 14px 0 6px; color: var(--text-1); }
.au-co-mini { width: 100%; }
.au-co-mini td, .au-co-mini th { font-size: 12.5px; padding: 7px 8px; }
.au-co-on { color: #16a34a; font-weight: 700; font-size: 12px; }
.au-co-pend { color: #b45309; font-weight: 700; font-size: 12px; }
.au-co-ret {
  display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap;
  border-top: 1px solid var(--border); margin-top: 16px; padding-top: 12px;
}
.au-co-ret label { font-size: 12px; color: var(--text-2); width: 100%; }
.au-co-ret input { width: 110px; }
.au-co-hint { flex-basis: 100%; font-size: 11px; color: var(--text-3); }
@media (max-width: 640px) {
  .au-co-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .au-co-namebtn { max-width: 100%; }
  .au-co-table td.au-co-acts { text-align: start; }
}
[dir="rtl"] .au-co-owner { text-align: right; }
[dir="rtl"] .au-co-namebtn { text-align: right; }

/* User card → "Security & Location" (registration IP / country / VPN) */
.au-sec {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 11px 14px; margin: 6px 0 12px; background: #fafaf9;
}
.au-sec-title {
  font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 8px;
}
.au-sec-row {
  display: flex; align-items: baseline; gap: 10px;
  padding: 3px 0; font-size: 13px;
}
.au-sec-row + .au-sec-row { border-top: 1px dashed var(--border); }
.au-sec-k { flex: 0 0 96px; color: var(--text-3); font-size: 12px; }
.au-sec-v { flex: 1 1 auto; min-width: 0; color: var(--text-1); font-weight: 600; word-break: break-word; }
.au-sec-ip {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 600; font-size: 12.5px; direction: ltr; unicode-bidi: isolate;
  text-align: start;
}
.au-sec-flag { font-size: 15px; line-height: 1; }
.au-sec-cc {
  font-size: 11px; font-weight: 700; color: var(--text-3);
  border: 1px solid var(--border); border-radius: 5px; padding: 0 4px;
}
.au-sec-badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 800; border-radius: 999px;
  padding: 2px 9px; border: 1px solid transparent; cursor: help;
}
.au-sec-badge.is-vpn { color: #b91c1c; background: #fef2f2; border-color: #fecaca; }
.au-sec-badge.is-direct { color: #15803d; background: #f0fdf4; border-color: #bbf7d0; }
.au-sec-badge.is-unknown { color: var(--text-3); background: #f5f5f4; border-color: var(--border); font-weight: 700; }
@media (max-width: 640px) {
  .au-sec-row { flex-direction: column; gap: 1px; }
  .au-sec-k { flex: none; }
}

/* =========================================================================
   Admin → Orders

   One table, built to be scanned: the person's name leads, the money shows the
   discount rather than hiding it, and the row's own action is the only colour on
   it. Colours come from the tokens so this follows an admin theme change.
   ========================================================================= */
.ord-stats {
  display: grid; gap: 10px; margin: 0 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.ord-stat {
  background: #fff; border: 1px solid var(--border); border-radius: 14px;
  padding: 12px 14px; box-shadow: 0 1px 2px rgba(15,23,42,.04);
  border-inline-start: 4px solid var(--brand-500, #6366f1);
}
.ord-stat.warn { border-inline-start-color: #d97706; }
.ord-stat.ok { border-inline-start-color: #16a34a; }
.ord-stat-l { font-size: 11.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--text-3); }
.ord-stat-v { font-size: 22px; font-weight: 800; line-height: 1.15; margin-top: 3px; color: var(--text-1); }
.ord-stat-s { font-size: 11.5px; color: var(--text-3); margin-top: 3px; line-height: 1.35; }

.ord-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0 0 12px; }
.ord-filters { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.ord-chip {
  border: 1px solid var(--border); background: #fff; color: var(--text-2);
  border-radius: 999px; padding: 5px 12px; font-size: 12.5px; cursor: pointer;
  font-family: inherit; transition: background .12s, border-color .12s;
}
.ord-chip:hover { border-color: var(--brand-500, #6366f1); }
.ord-chip b { font-weight: 800; margin-inline-start: 2px; }
.ord-chip.active { background: var(--brand-600, #4f46e5); border-color: var(--brand-600, #4f46e5); color: #fff; font-weight: 700; }
.ord-search { position: relative; flex: 1; min-width: 190px; }
.ord-search-ico { position: absolute; inset-inline-start: 10px; top: 50%; transform: translateY(-50%); color: var(--text-3); font-size: 13px; }
.ord-search input {
  width: 100%; box-sizing: border-box; border: 1px solid var(--border); border-radius: 10px;
  padding: 7px 11px 7px 32px; font-size: 13px; background: #fff; color: var(--text-1);
  font-family: inherit;
}
.ord-search input:focus { outline: none; border-color: var(--brand-500, #6366f1); }
.ord-del { border: 1px solid rgba(225,29,72,.45) !important; color: #be123c !important; background: #fff5f7 !important; font-weight: 700; white-space: nowrap; }
.ord-del:disabled { opacity: .45; cursor: not-allowed; }

.ord-count {
  padding: 10px 14px; font-size: 12.5px; color: var(--text-2);
  border-bottom: 1px solid var(--border);
}
.ord-table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 940px; }
.ord-th {
  text-align: start; padding: 9px 10px; color: var(--text-3); font-size: 11.5px;
  font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  border-bottom: 1px solid var(--border); white-space: nowrap; user-select: none;
}
.ord-th[data-osort] { cursor: pointer; }
.ord-th[data-osort]:hover { color: var(--brand-600, #4f46e5); }
.ord-th-cb { width: 34px; }
.ord-th-cb2 { width: 62px; }
.ord-td { padding: 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.ord-td-cb { width: 34px; padding-inline-end: 0; }
.ord-td-cb input, .ord-th-cb input { width: 16px; height: 16px; cursor: pointer; accent-color: var(--brand-500, #6366f1); }
.ord-td-id { color: var(--text-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ord-td-date { white-space: nowrap; color: var(--text-2); }
.ord-td-acts { white-space: nowrap; }
.ord-td-acts .btn { margin-inline-end: 4px; }
.ord-row-on { background: var(--brand-50, #eef2ff); }
.ord-name { font-weight: 700; color: var(--text-1); }
.ord-contact { font-size: 11.5px; color: var(--text-3); margin-top: 2px; word-break: break-word; }
.ord-contact a { color: var(--brand-600, #4f46e5); text-decoration: none; }
.ord-contact a:hover { text-decoration: underline; }
.ord-susp {
  font-size: 10px; font-weight: 800; color: #fff; background: #dc2626;
  border-radius: 999px; padding: 1px 7px; vertical-align: 1px;
}
.ord-code {
  font-size: 12px; background: var(--surface-2, #f1f5f9); border: 1px solid var(--border);
  border-radius: 6px; padding: 1px 6px; direction: ltr; display: inline-block;
}
.ord-amt { font-weight: 700; color: var(--text-1); white-space: nowrap; }
.ord-amt-sub { font-size: 11.5px; color: var(--text-3); white-space: nowrap; }
.ord-amt-sub b { color: #15803d; }
.ord-st { font-weight: 700; white-space: nowrap; }
.ord-pay { font-size: 11px; color: var(--text-3); margin-top: 3px; }
.ord-pay-ref { font-size: 10.5px; color: var(--text-3); margin-top: 1px; }
.ord-ok { background: #16a34a !important; border-color: #16a34a !important; color: #fff !important; font-weight: 700; }
.ord-done { font-size: 12px; color: #15803d; font-weight: 600; }
.ord-del-row { border: 1px solid var(--border) !important; color: #be123c !important; background: #fff !important; }
.ord-del-row:hover { background: #fff5f7 !important; border-color: rgba(225,29,72,.45) !important; }

/* ===========================================================================
   ADMIN → BROADCAST

   Built from the same pieces as the rest of the admin area, not a new visual
   language: white cards with a hairline border and a soft shadow (`.au-card`),
   the admin blue gradient `#1b74bc → #2f8fd6` for the primary action, and the
   `--r-*` / `--text-*` / `--border` tokens for everything else.

   The one deliberate exception is the primary button's GRADIENT: the rest of the
   app uses the indigo/cyan brand ramp, but the admin area's "do the thing"
   buttons (the FAB, the users pager, the avatars) use this blue, and Broadcast
   sits in the admin area. It is written once, here, as `.bc-btn-primary`.
   =========================================================================== */
.bc-wrap { display: flex; flex-direction: column; gap: 16px; }

/* ---- card ---------------------------------------------------------------- */
.bc-card {
  background: #fff; border: 1px solid var(--border); border-radius: 16px;
  padding: 18px 18px 16px; box-shadow: 0 1px 2px rgba(15,23,42,.04);
}
.bc-head {
  display: flex; align-items: center; gap: 9px;
  font-weight: 800; font-size: 15px; color: var(--text);
  margin: 0 0 14px;
}
.bc-head .bc-ico { font-size: 17px; line-height: 1; }
/* A right-hand slot in the header for a small control (e.g. the preview toggle) */
.bc-head .bc-head-end { margin-inline-start: auto; font-weight: 600; }

/* ---- fields -------------------------------------------------------------- */
.bc-field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.bc-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.bc-label { font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.bc-input, .bc-select, .bc-textarea {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px;
  color: var(--text); background: #fff; border: 1px solid var(--border);
  border-radius: 10px; padding: 9px 12px; transition: border-color .15s, box-shadow .15s;
}
.bc-input:focus, .bc-select:focus, .bc-textarea:focus {
  outline: none; border-color: #2f8fd6; box-shadow: 0 0 0 3px rgba(47,143,214,.16);
}
.bc-textarea { resize: vertical; min-height: 132px; line-height: 1.6; }

/* ---- rich-text announcement editor --------------------------------------- */
/* The message box is a contenteditable now, so it needs its own frame: the
   toolbar owns the top border, the editor owns the rest, and the focus ring
   wraps BOTH (a ring around the text alone would read as a different field). */
.bc-editor-wrap {
  border: 1px solid var(--border); border-radius: 10px; overflow: hidden;
  background: #fff; transition: border-color .15s, box-shadow .15s;
}
.bc-editor-wrap:focus-within { border-color: #2f8fd6; box-shadow: 0 0 0 3px rgba(47,143,214,.16); }
/* Visual / HTML — the same segmented pill the Users list uses for its layouts,
   so "choose how you see this" looks the same everywhere in the admin. */
.bc-tabs {
  display: inline-flex; border: 1px solid var(--border); border-radius: 999px;
  overflow: hidden; background: #fff; margin-bottom: 8px;
}
.bc-tab {
  border: 0; background: transparent; color: var(--text-2); font: inherit;
  font-size: 12.5px; font-weight: 700; line-height: 1; padding: 7px 16px; cursor: pointer;
  transition: background .12s, color .12s;
}
.bc-tab + .bc-tab { border-inline-start: 1px solid var(--border); }
.bc-tab:hover { background: var(--surface); color: #1b74bc; }
.bc-tab.on { background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff; }
/* `hidden` must win over these elements' own `display` (the toolbar is flex, the
   source is block), or the code view would show the formatting buttons that
   cannot apply to it and the editor would show alongside the source. */
.bc-toolbar[hidden], .bc-editor[hidden], .bc-source[hidden] { display: none; }
/* The HTML source view. Always LTR and monospaced — a code editor laid out
   right-to-left (which the Farsi UI would otherwise do) puts `<td>` and its
   closing `>` in the wrong visual order and is genuinely hard to read. */
.bc-source {
  display: block; width: 100%; box-sizing: border-box;
  min-height: 190px; max-height: 420px; resize: vertical;
  border: 0; outline: none; padding: 12px 14px; margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
  font-size: 12.5px; line-height: 1.6; tab-size: 2;
  color: var(--text); background: #fff;
  direction: ltr; text-align: left;
}
.bc-toolbar {
  position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  padding: 6px 8px; border-bottom: 1px solid var(--border); background: var(--surface);
}
.bc-tb {
  font: inherit; font-size: 13px; line-height: 1; min-width: 30px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  border: 1px solid transparent; border-radius: 8px; background: transparent;
  color: var(--text-2); cursor: pointer; padding: 0 7px;
  transition: background .12s, color .12s, border-color .12s;
}
.bc-tb:hover { background: #eef6fc; color: #1b74bc; border-color: #d6e8f6; }
/* The caret's own state, not the last click: the button reads "on" when the
   selection is already bold, exactly like a word processor's toolbar. */
.bc-tb.on { background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff; }
.bc-tb-sep { width: 1px; height: 18px; background: var(--border); margin: 0 3px; }
.bc-editor {
  min-height: 132px; max-height: 420px; overflow-y: auto;
  padding: 10px 12px; font-size: 14px; line-height: 1.65;
  color: var(--text); outline: none; word-break: break-word;
}
.bc-editor:empty:before { content: attr(data-bc-ph); color: var(--text-3); }
.bc-editor img { max-width: 100%; height: auto; border-radius: 8px; }
.bc-editor blockquote {
  margin: 6px 0; padding: 2px 12px; color: var(--text-2);
  border-inline-start: 3px solid var(--border-2);
}
/* ===========================================================================
   Admin → Blog — only what the ARTICLE editor adds on top of the broadcast
   editor it reuses (`bc-editor`, `bc-tabs`, `bc-toolbar`, `bc-source` are all
   shared, so the two admin composers cannot drift apart visually).
   =========================================================================== */
/* Each language is a full edition of the same article, so the English and Farsi
   forms are sibling panes and only one is ever shown. */
.bl-pane[hidden] { display: none; }
/* Headings, lists and code, SCOPED to `.bl-pane`: the broadcast editor only ever
   had to style a short announcement, and an article is mostly headings,
   paragraphs and lists. Scoping means the broadcast composer's appearance is
   untouched by these rules. */
.bl-pane .bc-editor h1, .bl-pane .bc-editor h2, .bl-pane .bc-editor h3,
.bl-pane .bc-editor h4 {
  margin: .7em 0 .3em; line-height: 1.3; font-weight: 700;
}
.bl-pane .bc-editor h1 { font-size: 21px; }
.bl-pane .bc-editor h2 { font-size: 18px; }
.bl-pane .bc-editor h3 { font-size: 16px; }
.bl-pane .bc-editor h4 { font-size: 15px; }
.bl-pane .bc-editor p { margin: .45em 0; }
.bl-pane .bc-editor ul, .bl-pane .bc-editor ol { margin: .5em 0; padding-inline-start: 1.6em; }
.bl-pane .bc-editor li { margin: .2em 0; }
/* A code block is LTR even in the Farsi editor — code is code, and an RTL block
   reorders the punctuation of something like `enc:v1:...`. */
.bl-pane .bc-editor pre {
  margin: .6em 0; padding: 10px 12px; border-radius: 8px;
  background: #0f172a; color: #e2e8f0; overflow-x: auto;
  direction: ltr; text-align: start; font-size: 12.5px;
}
.bl-pane .bc-editor hr { border: 0; border-block-start: 1px solid var(--border); margin: 1em 0; }
/* A pasted article can carry a table (the security post does). */
.bl-pane .bc-editor table { border-collapse: collapse; margin: .6em 0; font-size: 13px; }
.bl-pane .bc-editor th, .bl-pane .bc-editor td {
  border: 1px solid var(--border); padding: 6px 8px; text-align: start;
}
/* The "not written in this language" hint above the Farsi form. */
.bl-lang-note {
  margin: 0 0 10px; padding: 8px 12px; border-radius: 8px;
  background: #fff7ed; border: 1px solid #fed7aa; color: #9a3412;
  font-size: 12.5px;
}
/* Cover image row: a fixed-ratio preview so the admin sees the crop the blog
   index and the Open Graph card will use. */
.bl-cover-row { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.bl-cover-preview {
  width: 168px; height: 96px; flex: 0 0 auto; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--border-2); border-radius: 10px; background: var(--surface);
}
.bl-cover-preview img { width: 100%; height: 100%; object-fit: cover; }
.bl-cover-empty { font-size: 26px; opacity: .5; }
.bl-cover-actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* Emoji picker: a small grid anchored to the toolbar button, not a modal — it
   must not take the caret away from the message the emoji goes into. */
.bc-emoji-pop {
  position: absolute; top: calc(100% + 4px); inset-inline-end: 8px; z-index: 30;
  display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px;
  width: 288px; max-height: 190px; overflow-y: auto; padding: 6px;
  background: #fff; border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 12px 30px rgba(15,23,42,.18);
}
.bc-emoji {
  font-size: 17px; line-height: 1; border: 0; background: transparent;
  border-radius: 6px; padding: 5px 0; cursor: pointer;
}
.bc-emoji:hover { background: var(--surface-2); }

/* The live audience count under the target dropdown. */
.bc-audience {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 7px;
  font-size: 12.5px; font-weight: 600; color: #1b74bc;
  background: #eef6fc; border: 1px solid #d6e8f6; border-radius: 999px;
  padding: 4px 12px;
}
.bc-audience.bc-audience-warn { color: #b45309; background: #fffbeb; border-color: #fde68a; }

/* ---- delivery-method checkboxes + tier checkboxes ------------------------ */
/* Three INDEPENDENT channels, and a multi-select tier list. Both are the same
   control: a wrapped row of pill checkboxes, so a long tier label never crushes
   the layout. */
.bc-checks { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 2px; }
.bc-check {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600; color: var(--text-2); cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 12px; transition: border-color .12s ease, background .12s ease;
}
.bc-check:hover { border-color: var(--border-2); background: #fff; }
.bc-check input { width: 16px; height: 16px; accent-color: #1b74bc; cursor: pointer; }
/* The inline "select at least one" warning (req 4) and the tier equivalent. */
.bc-inline-warn {
  margin-top: 8px; font-size: 12.5px; font-weight: 600; color: #b45309;
  background: #fffbeb; border: 1px solid #fde68a; border-radius: 9px;
  padding: 7px 11px;
}
/* The SMS recipient-count / estimated-cost note (req 5), inline under the
   checkboxes while SMS is ticked. */
.bc-sms-note {
  margin-top: 8px; font-size: 12.5px; font-weight: 600; color: #1b74bc;
  background: #eef6fc; border: 1px solid #d6e8f6; border-radius: 9px;
  padding: 7px 11px;
}
.bc-sms-note.on { display: block; }
/* The bulk confirmation modal's cost line reuses the same look, in amber. */
.bc-modal .bc-sms-note.on { color: #b45309; background: #fffbeb; border-color: #fde68a; margin: 12px 0 0; }


/* ---- character budget: a bar, not a whisper ------------------------------ */
.bc-count-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.bc-count { font-size: 12px; font-weight: 700; color: var(--text-3); font-variant-numeric: tabular-nums; }
.bc-count.warn { color: #b45309; }
.bc-count.over { color: #dc2626; }
.bc-bar { height: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; margin: 7px 0 14px; }
.bc-bar-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(135deg, #1b74bc, #2f8fd6);
  transition: width .18s ease, background .18s ease;
}
/* Near the limit it turns amber, past it red — the two states the operator has to
   be able to see without reading the number. */
.bc-bar-fill.warn { background: linear-gradient(135deg, #f59e0b, #fbbf24); }
.bc-bar-fill.over { background: linear-gradient(135deg, #dc2626, #ef4444); }

/* ---- buttons (Halo style) ------------------------------------------------ */
.bc-actions { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; }
.bc-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-size: 13.5px; font-weight: 700; line-height: 1;
  border-radius: 999px; padding: 10px 18px; cursor: pointer;
  border: 1px solid transparent; background: var(--surface-2); color: var(--text-2);
  transition: transform .12s ease, box-shadow .15s ease, background .15s ease, color .15s;
  white-space: nowrap;
}
.bc-btn:hover { transform: translateY(-1px); }
.bc-btn:active { transform: translateY(0); }
.bc-btn:disabled { opacity: .55; cursor: default; transform: none; box-shadow: none; }
.bc-btn-primary {
  background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff;
  box-shadow: 0 2px 8px rgba(27,116,188,.28);
}
.bc-btn-primary:hover:not(:disabled) { box-shadow: 0 8px 20px rgba(27,116,188,.42); }
.bc-btn-ghost { background: #fff; border-color: var(--border); color: var(--text-2); }
.bc-btn-ghost:hover:not(:disabled) { background: var(--surface); border-color: var(--border-2); color: var(--text); }
.bc-btn-danger { background: #fff; border-color: #fecaca; color: #dc2626; }
.bc-btn-danger:hover:not(:disabled) { background: #fef2f2; box-shadow: 0 4px 14px rgba(220,38,38,.16); }
.bc-hint { font-size: 12px; color: var(--text-3); }

/* ---- send-later toggle --------------------------------------------------- */
.bc-toggle { display: inline-flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 600; color: var(--text-2); cursor: pointer; }
.bc-toggle input { width: 16px; height: 16px; accent-color: #1b74bc; cursor: pointer; }
.bc-later { display: none; margin-top: 12px; }
.bc-later.on { display: block; }

/* ---- preview: what the user actually sees -------------------------------- */
.bc-preview { display: none; margin-top: 4px; }
.bc-preview.on { display: block; }
.bc-preview-label { font-size: 11.5px; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; }
/* A mock of the in-app notification row, so it reads as "the user's inbox". */
.bc-inbox { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 10px; }
.bc-inbox-top { display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--text-3); padding: 2px 4px 8px; }
.bc-inbox-dot { width: 7px; height: 7px; border-radius: 50%; background: #1b74bc; flex: none; }
.bc-inbox-row {
  background: #fff; border: 1px solid var(--border); border-radius: 12px;
  padding: 12px 14px; display: flex; gap: 12px; align-items: flex-start;
  box-shadow: 0 1px 2px rgba(15,23,42,.05);
}
.bc-inbox-ico {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: linear-gradient(135deg, #1b74bc, #2f8fd6); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
}
.bc-inbox-title { font-weight: 800; font-size: 13.5px; color: var(--text); }
/* `white-space: normal`, not pre-wrap: an announcement is HTML now (blocks are
   <div>/<br>), and pre-wrap would render every newline and indent in a PASTED
   email's source as a blank gap. The box scrolls so a 600px-wide pasted layout
   cannot stretch the composer. */
.bc-inbox-body {
  font-size: 13px; color: var(--text-2); line-height: 1.6;
  white-space: normal; word-break: break-word; margin-top: 3px;
  max-height: 420px; overflow: auto;
}
.bc-inbox-meta { font-size: 11.5px; color: var(--text-3); margin-top: 6px; }

/* ---- recent broadcasts table -------------------------------------------- */
.bc-table-wrap { overflow-x: auto; }
.bc-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.bc-table th {
  text-align: start; font-size: 11px; font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-3); padding: 0 10px 9px;
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
.bc-table td { padding: 11px 10px; border-bottom: 1px solid var(--surface-2); color: var(--text-2); vertical-align: middle; }
.bc-table tr:last-child td { border-bottom: none; }
.bc-table tbody tr:hover { background: var(--surface); }
.bc-table .bc-subject { font-weight: 700; color: var(--text); }
.bc-table .bc-subject .bc-body-hint { display: block; font-weight: 400; font-size: 11.5px; color: var(--text-3); margin-top: 2px; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bc-num { font-variant-numeric: tabular-nums; }
.bc-row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.bc-row-actions .bc-btn { padding: 6px 12px; font-size: 12px; }

/* ---- status pill --------------------------------------------------------- */
.bc-status {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  font-weight: 800; border-radius: 999px; padding: 3px 10px; white-space: nowrap;
}
.bc-status-sent { background: #ecfdf5; color: #047857; }
.bc-status-scheduled { background: #eef6fc; color: #1b74bc; }
.bc-status-draft { background: var(--surface-2); color: var(--text-2); }
.bc-status-failed { background: #fef2f2; color: #dc2626; }

.bc-empty { text-align: center; color: var(--text-3); font-size: 13px; padding: 26px 10px; }

/* ---- pagination (same shape as the users page pager) --------------------- */
.bc-pager { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.bc-pager .p-btn {
  border: 1px solid var(--border); background: #fff; color: var(--text-2);
  border-radius: 8px; padding: 5px 11px; font-size: 13px; cursor: pointer;
}
.bc-pager .p-btn.on { background: #1b74bc; color: #fff; border-color: #1b74bc; font-weight: 700; }
.bc-pager .p-btn:disabled { opacity: .4; cursor: default; }

/* ---- confirmation modal -------------------------------------------------- */
.bc-modal-back {
  position: fixed; inset: 0; z-index: 90; background: rgba(15,23,42,.5);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.bc-modal {
  background: #fff; border-radius: 16px; padding: 22px; width: 100%; max-width: 460px;
  box-shadow: 0 24px 60px rgba(15,23,42,.32);
}
.bc-modal h3 { margin: 0 0 8px; font-size: 17px; font-weight: 800; color: var(--text); }
.bc-modal p { margin: 0; font-size: 13.5px; line-height: 1.7; color: var(--text-2); }
.bc-modal .bc-quote {
  margin: 12px 0; padding: 10px 13px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--border);
  font-size: 13px; color: var(--text); font-weight: 600;
}
.bc-modal-actions { display: flex; gap: 9px; justify-content: flex-end; margin-top: 18px; }

/* ---- narrow screens: one column ----------------------------------------- */
@media (max-width: 820px) {
  .bc-grid2 { grid-template-columns: 1fr; }
  .bc-card { padding: 15px; border-radius: 14px; }
  .bc-actions .bc-btn { flex: 1 1 auto; }
  .bc-row-actions { justify-content: flex-start; }
  .bc-table th:nth-child(2), .bc-table td:nth-child(2) { display: none; }  /* the date column */
}

/* =========================================================================
   Phones: a row of action buttons spans the full width
   -------------------------------------------------------------------------
   Reported: "the action buttons do not fill the width of the screen and
   sometimes look staggered." A footer built as
   `<div style="display:flex;justify-content:flex-end;gap:10px">…</div>` sat at
   its natural size against the right edge, and when it wrapped the second line
   left a ragged (staggered) edge. Below 640px a row that holds two or more of
   the app's action buttons now WRAPS and every button in that row GROWS to
   share the line, so the row reads edge to edge and a wrapped line never
   staggers.

   Two safety rails, both structural (so they cannot rot as views change):
     * `body.dash-body` — the app shell's own body class. The marketing pages
       that also load this file (landing, pricing, studios, blog …) have a
       different body class, so their buttons are untouched.
     * `:has(> A + A)` — restricts the rule to ROWS: a lone button beside a
       heading (a header) has no button sibling and keeps its natural size, as do
       `.notify-foot` (which already stacks full-width) and toolbar rows that use
       a `.spacer` (e.g. Admin → Users' Export/Import/…/Add bar).
   `.btn-mini` — the tiny inline utilities on media tiles, folder rows and list
   rows — is deliberately NOT in the list, so those dense controls keep their
   size. `:has()` is a progressive enhancement: where it is unsupported the
   block simply does not apply.
   ========================================================================= */
@media (max-width: 640px) {
  /* The design system's large action buttons, in any row of two or more. */
  body.dash-body div:not(.notify-foot):not(:has(> .spacer)):has(> :is(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger) + :is(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger)) {
    flex-wrap: wrap;
  }
  body.dash-body div:not(.notify-foot):not(:has(> .spacer)):has(> :is(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger) + :is(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger)) > :is(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger) {
    flex: 1 1 44%;
    min-width: 0;
    box-sizing: border-box;
    justify-content: center;
  }

  /* The studios, the studio wizard and their pop-ups use their own button
     classes; the same "fill the line" rule is applied to their action rows. */
  .studio-card-actions .st-btn,
  .st-cmp-foot .st-btn,
  .sw-foot .sw-btn,
  .vm-card-acts .vm-btn,
  .vm-foot .vm-btn,
  .ts-sum-actions .ts-mini,
  .ts-job-actions .ts-mini,
  .ob-actions .ob-skip,
  .ob-actions .ob-primary {
    flex: 1 1 44%;
    min-width: 0;
    /* `box-sizing` matters: an action button may be an <a> (e.g. an .st-btn
       download link), which is content-box by default — its padding then made it
       wider than the <button> beside it and the row wrapped unevenly (2/1/2
       rather than 2/2/1). */
    box-sizing: border-box;
    justify-content: center;
  }
  .studio-card-actions,
  .st-cmp-foot,
  .sw-foot,
  .vm-card-acts,
  .vm-foot,
  .ts-sum-actions,
  .ts-job-actions,
  .ob-actions {
    flex-wrap: wrap;
  }
  /* The Video Maker footer's "≈ 1 min · 12 MB" estimate takes its own line so the
     two buttons underneath share the width evenly. */
  .vm-foot .vm-est { flex: 1 1 100%; text-align: start; }
}

/* ==========================================================================
   2026-10-17 — Sidebar redesign: workspace switcher, collapsible sections,
   monochrome line icons, fixed footer. Scoped to .sidebar so the landing
   pages and the client gallery (which also load design.css) are untouched.
   ========================================================================== */
.sidebar { background: #0b1220; }
.sidebar .sb-brand { padding: 18px 16px 12px; border-bottom: 0; }
.sidebar .sb-brand .brand-logo { height: 30px; }

/* Workspace switcher — a pill that reads "Current Workspace  ▾".
   Tinted with the app's OWN theme tokens (--brand-*) instead of a second,
   unrelated navy/blue: the switcher is chrome of the same system as the active
   menu row, so it must not look like a control borrowed from another product.
   `color-mix` is layered over a plain-rgba fallback so older mobile browsers
   keep a readable pill instead of losing the background entirely. */
.sb-workspace { padding: 0 12px 12px; border-bottom: 1px solid rgba(99, 102, 241, .20); }
.sb-ws-label {
  display: block; margin: 2px 6px 6px; font-size: 9.5px; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; color: #64748b;
}
.sb-ws-select {
  width: 100%; appearance: none; -webkit-appearance: none; cursor: pointer;
  padding: 9px 34px 9px 14px; border-radius: 999px;
  /* Fallback for engines without color-mix(). */
  border: 1px solid rgba(129, 140, 248, .42);
  border-color: color-mix(in srgb, var(--brand-500) 42%, transparent);
  background-color: rgba(79, 70, 229, .16);
  background-color: color-mix(in srgb, var(--brand-600) 16%, #0b1220);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a5b4fc' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
  background-size: 14px; color: #eef2ff; font: inherit; font-size: 12.5px;
  font-weight: 700; transition: border-color .15s, background-color .15s;
}
html[dir="rtl"] .sb-ws-select {
  padding: 9px 14px 9px 34px; background-position: left 12px center;
}
.sb-ws-select:hover {
  border-color: var(--brand-400);
  background-color: color-mix(in srgb, var(--brand-600) 30%, #0b1220);
}
.sb-ws-select:focus { outline: 2px solid var(--brand-500); outline-offset: 1px; }
.sb-ws-select option { background: #0b1220; color: #eef2ff; }

.sidebar .sb-nav { padding: 8px 10px 18px; gap: 1px; }
.sb-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Section accordion. */
.sb-group-wrap { display: flex; flex-direction: column; }
.sb-group {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 13px 10px 7px; background: transparent; border: 0; cursor: pointer;
  color: #8b9ab3; font: inherit; font-size: 10px; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; text-align: start;
  transition: color .15s;
}
.sb-group:hover { color: #e2e8f0; }
.sb-group-ico { display: inline-flex; flex: none; }
.sb-group-ico svg, .sb-group .sb-chev {
  width: 15px; height: 15px; stroke: currentColor; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.sb-group-lbl { flex: 1; }
.sb-group .sb-chev { flex: none; color: #cbd5e1; stroke-width: 2.4; transition: transform .2s ease; }
.sb-group-wrap.open > .sb-group .sb-chev { transform: rotate(180deg); }
.sb-group-body { display: flex; flex-direction: column; gap: 2px; }
.sb-group-wrap:not(.open) > .sb-group-body { display: none; }

/* Dashboard + Compose are pinned above every section (and above Photography
   when that workspace is selected): a small primary block with air under it. */
.sb-nav > .sb-pinned-wrap {
  display: flex; flex-direction: column; gap: 4px; margin: 2px 2px 8px;
}
.sb-pinned-wrap .sb-item .sb-ico svg { stroke-width: 1.8; }

/* Nav rows: more air, one hover language, brand gradient ONLY when active. */
.sidebar .sb-item {
  gap: 12px; padding: 11px 12px; border-radius: 11px;
  color: #b9c4d8; font-size: 13.5px; font-weight: 600;
  transition: background .15s, color .15s, box-shadow .15s;
}
.sidebar .sb-item:hover { background: #16203a; color: #fff; }
.sidebar .sb-item.active {
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #fff; box-shadow: 0 8px 20px rgba(99, 102, 241, .26);
}
.sidebar .sb-item .sb-ico { width: 20px; }
.sb-item .sb-ico svg {
  width: 19px; height: 19px; stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.sidebar .sb-item.pg-nav {
  background: transparent; color: #b9c4d8; font-weight: 600; box-shadow: none;
}
.sidebar .sb-item.pg-nav:hover { background: #16203a; color: #fff; }

/* Workspace visibility: Photography is a Photographer-only shelf. */
.sidebar[data-workspace="general"] .ws-photography { display: none; }
/* ...and the managing/account shelves have a workspace of their own now, so
   General is purely the making-things rail. The Admin shelf carries `ws-manage`
   too (it is management, and admins get it under Manage & Account), which is
   what keeps it off the General rail. */
.sidebar[data-workspace="general"] .ws-manage { display: none; }

/* ...and the Photographer workspace is that shelf ONLY. Dashboard/Compose stay
   pinned in every workspace — they are the two places a visit starts, and hiding
   them turned a workspace switch into a dead end. */
.sidebar[data-workspace="photographer"] .sb-group-wrap:not(.ws-photography) {
  display: none;
}

/* Manage & Account: the other half of the job — scheduling, media, reports and
   the account itself. Admin rides along (it IS management; the wrapper keeps its
   own display:none for non-admins). */
.sidebar[data-workspace="manage"] .sb-group-wrap:not(.ws-manage):not(.admin-only) {
  display: none;
}

/* Fixed footer. */
.sidebar .sb-foot {
  padding: 12px; border-top: 1px solid #16203a; background: #0b1220;
}
.sb-foot .sb-profile {
  background: #111a2e; border: 1px solid #1e293b; border-radius: 11px;
  margin-bottom: 10px; color: #dbe4f3;
}
.sb-foot .sb-profile:hover { background: #16203a; }
.sb-foot .sb-item.sb-upgrade {
  width: 100%; justify-content: center; gap: 8px; padding: 11px 14px;
  border-radius: 999px; color: #fff; font-weight: 800; font-size: 13px;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  box-shadow: 0 10px 22px rgba(99, 102, 241, .30);
}
.sb-foot .sb-item.sb-upgrade:hover {
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
  box-shadow: 0 12px 26px rgba(99, 102, 241, .38);
}
.sb-foot .sb-item.sb-upgrade.disabled { opacity: .45; cursor: not-allowed; }
.sb-foot #btnLogout {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; margin-top: 8px; padding: 10px 12px; border: 1px solid transparent;
  border-radius: 10px; background: transparent; color: #7f8ea8;
  font-size: 12.5px; font-weight: 600; cursor: pointer;
  transition: background .15s, color .15s;
}
.sb-foot #btnLogout.hidden { display: none; }
.sb-foot #btnLogout:hover { background: #16203a; color: #fff; border-color: transparent; }
.sb-foot #btnLogout svg {
  width: 17px; height: 17px; stroke: currentColor; fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}

/* Collapsed icon rail: no headers, every group's items visible as icons. */
.app-shell.sb-min .sidebar .sb-workspace { display: none; }
.app-shell.sb-min .sidebar .sb-group { display: none; }
.app-shell.sb-min .sidebar .sb-group-body { display: flex !important; }
.app-shell.sb-min .sidebar .sb-subgroup { display: none; }
.app-shell.sb-min .sidebar .sb-sub-body { display: flex !important; padding-inline-start: 0; }
.app-shell.sb-min .sidebar .sb-item { justify-content: center; padding: 11px 6px; }
.app-shell.sb-min .sidebar .sb-item > span:not(.sb-ico) { display: none; }
.app-shell.sb-min .sidebar .sb-logout span { display: none; }
.app-shell.sb-min .sidebar #btnLogout { justify-content: center; padding: 9px 6px; }

/* ---- Dashboard launchpad (grouped tiles) ---------------------------------
   Three labelled groups instead of one flat grid, monochrome line icons in a
   soft rounded square per tile, bold titles and quieter descriptions. Every
   tile shares the same radius, border and shadow so the grid reads as a set. */
.dash-launch { margin-top: 22px; display: flex; flex-direction: column; gap: 26px; }
.dash-group-title {
  margin: 0 0 10px; font-size: 11px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--text-3, #64748b);
}
.dash-tiles {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.dash-tile {
  display: flex; align-items: center; gap: 14px; text-align: start;
  padding: 15px 16px; min-height: 84px; cursor: pointer;
  border: 1px solid var(--border, #e2e8f0); border-radius: 16px;
  background: var(--surface, #fff); font-family: inherit;
  color: var(--text, #0f172a); text-decoration: none;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04), 0 8px 20px -14px rgba(15, 23, 42, .35);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.dash-tile:hover {
  border-color: var(--brand-400, #818cf8);
  transform: translateY(-2px);
  box-shadow: 0 12px 26px -14px rgba(79, 70, 229, .45);
}
.dash-tile:focus-visible { outline: 2px solid var(--brand-500, #6366f1); outline-offset: 2px; }
.dash-tile-ico {
  flex: none; width: 44px; height: 44px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: #eef2ff; color: #4f46e5;
}
.dash-tile-ico svg {
  width: 22px; height: 22px; stroke: currentColor; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.dash-tile-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dash-tile-txt b { font-size: 14.5px; font-weight: 800; letter-spacing: -.01em; }
.dash-tile-txt small { font-size: 12.5px; font-weight: 500; color: #94a3b8; line-height: 1.35; }

@media (max-width: 560px) {
  .dash-tiles { grid-template-columns: 1fr; gap: 10px; }
  .dash-tile { min-height: 72px; padding: 12px 14px; }
}

/* Dashboard KPI cards share the tile language: one line icon in a soft square. */
.dash-kpi-ico {
  flex: none; width: 46px; height: 46px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  background: #eef2ff; color: #4f46e5;
}
.dash-kpi-ico svg {
  width: 22px; height: 22px; stroke: currentColor; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* Plan / usage strip: same line-icon-in-a-soft-square language as the tiles. */
.pc-ico {
  flex: none; width: 38px; height: 38px; border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  background: #eef2ff; color: #4f46e5;
}
.pc-ico svg {
  width: 19px; height: 19px; stroke: currentColor; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* ---- Media Library search placement (phones) ------------------------------
   In the Media page (#mediaView, static/shell.js) the search box used to sit
   FIRST inside the toolbar, so on a phone it wrapped into the middle of the
   buttons and read as part of them. It is now its own flex row at the BOTTOM of
   the toolbar — i.e. directly above the media items (and the list view's column
   title bar), which is where a file filter belongs. Desktop is unchanged: the
   wrapper sits inline, before "New folder". */
.media-search-wrap {
  display: inline-flex; flex: 0 1 200px; min-width: 0;
}
.media-search-wrap > input { flex: 1 1 auto; }
@media (max-width: 700px) {
  /* `order` moves it after every button WITHOUT moving it in the DOM, so the one
     input (and the one listener attached to it) is untouched. */
  .media-search-wrap { order: 99; flex: 1 0 100%; }
}

/* ---- Ctrl+Z undo pill (window.SSUndo.grace — see shell.js) ----------------
   The ONE countdown notice on the site: a send is held for five seconds so it
   can still be taken back, and this is the only place that says so. It sits at
   the very top, above every modal (the account dialogs use z-[80]/z-[100]), and
   the ring around the number drains as the window closes.

   `--ss-undo-left` is set by the JS as a 1 → 0 fraction, so the ring and the
   number can never disagree about how long is left. */
.ss-undo-pill {
  position: fixed; top: 14px; left: 50%; transform: translateX(-50%);
  z-index: 100000; display: flex; align-items: center; gap: 10px;
  max-width: calc(100vw - 24px); box-sizing: border-box;
  padding: 8px 10px 8px 14px; border-radius: 999px;
  background: #0f172a; color: #fff; white-space: nowrap;
  box-shadow: 0 12px 34px rgba(15, 23, 42, .32);
  font-size: 13.5px; line-height: 1.25; font-weight: 600;
  animation: ss-undo-in .18s ease-out;
}
@keyframes ss-undo-in {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}
.ss-undo-pill .ss-undo-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 999px; flex: 0 0 auto;
  background: rgba(255, 255, 255, .12); font-size: 13px;
}
.ss-undo-pill .ss-undo-msg {
  overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* No physical keyboard on a phone, so the chord is not advertised there. */
.ss-undo-pill .ss-undo-hint { display: inline-flex; gap: 3px; flex: 0 0 auto; opacity: .72; }
@media (hover: none) and (pointer: coarse) {
  .ss-undo-pill .ss-undo-hint { display: none; }
}
.ss-undo-pill .ss-undo-hint kbd {
  font: 600 10.5px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: rgba(255, 255, 255, .14); border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 5px; padding: 0 5px;
}
.ss-undo-pill .ss-undo-btn {
  flex: 0 0 auto; cursor: pointer; border: 0; border-radius: 999px;
  padding: 6px 14px; background: #22c55e; color: #06281a;
  font-weight: 800; font-size: 13px;
}
.ss-undo-pill .ss-undo-btn:hover { background: #34d977; }
.ss-undo-pill .ss-undo-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.ss-undo-pill .ss-undo-count {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: conic-gradient(#22c55e calc(var(--ss-undo-left, 1) * 360deg),
                             rgba(255, 255, 255, .18) 0);
  transition: background .1s linear;
}
.ss-undo-pill .ss-undo-count > span {
  width: 20px; height: 20px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: #0f172a; font: 700 11.5px/1 ui-monospace, Menlo, monospace;
}
body[dir="rtl"] .ss-undo-pill { direction: rtl; }

/* ---- Marketing flyer editor: alignment buttons ---------------------------
   The three buttons carry Word's own align icons (four rules, the short ones
   ragged to the side), so they have to look like pressed buttons when the block
   is aligned that way — and an inline SVG has to be a block to sit centred. */
#mkEdBar .btn svg { display: block; }
#mkEdBar .btn.on {
  background: #0f172a; color: #fff; border-color: #0f172a;
}
#mkEdBar .btn.on svg { stroke: #fff; }
#mkEdBar select#mkEdFont { max-width: 158px; }

/* ---- Marketing flyer editor: the Properties panel ------------------------
   The right-hand sidebar (Admin → Marketing → Edit design). Text formatting
   moved here from the toolbar, so these rows ARE the editor's form: a label
   column and a control column, one line per property. */
#mkEdProps { font-size: 12.5px; }
#mkEdProps .mk-prop-title {
  font-weight: 800; font-size: 13.5px; margin-bottom: 10px; color: var(--text-1);
}
#mkEdProps .mk-prop-h {
  font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-3); margin: 0 0 8px;
}
#mkEdProps .mk-prop-h:not(:first-of-type) {
  margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--border);
}
#mkEdProps .mk-prop-row {
  display: flex; align-items: center; gap: 10px; padding: 4px 0;
}
#mkEdProps .mk-prop-k { flex: 0 0 92px; color: var(--text-3); font-size: 12px; }
#mkEdProps .mk-prop-v { flex: 1 1 auto; min-width: 0; }
#mkEdProps .mk-prop-hint {
  margin-top: 10px; font-size: 11.5px; line-height: 1.5; color: var(--text-3);
}
/* The panel's B / I / align toggles are the same pressed state as the toolbar's
   used to be, but the toolbar selector is gone — they live here now. */
#mkEdProps .btn.on {
  background: #0f172a; color: #fff; border-color: #0f172a;
}
#mkEdProps .btn.on svg { stroke: #fff; }
#mkEdProps .btn:disabled { opacity: .45; cursor: not-allowed; }
#mkEdProps input[type="color"] { cursor: pointer; }
#mkEdProps input[type="range"] { accent-color: var(--brand-600, #4f46e5); }
@media (max-width: 640px) {
  #mkEdProps .mk-prop-row { flex-direction: column; align-items: stretch; gap: 3px; }
  #mkEdProps .mk-prop-k { flex: none; }
}

/* ==========================================================================
   B2B MARKETING DESIGN SUITE
   One gallery grid, a left-hand toolkit rail, the three-step wizard, and the
   brand-colour swatches. The gallery classes are shared by the admin template
   shelf and a company's own designs, which is what makes the two pages read as
   one feature instead of two.
   ========================================================================== */

/* ---- the ONE gallery grid (admin templates + company designs) ------------ */
.mk-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
  align-items: stretch;
}
.mk-gallery-card {
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--border);
  min-width: 0;
}
.mk-gallery-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 210px;
  padding: 14px;
  border: 0;
  background: var(--surface-2, #f1f5f9);
  cursor: pointer;
}
.mk-gallery-thumb img {
  max-width: 100%;
  max-height: 182px;
  background: #fff;
  box-shadow: 0 3px 12px rgba(15, 23, 42, .18);
}
.mk-gallery-ph { font-size: 34px; color: var(--text-3); }
.mk-gallery-body {
  padding: 10px 12px 4px;
  border-top: 1px solid var(--border);
  flex: 1 1 auto;
  min-width: 0;
}
.mk-gallery-title {
  font-weight: 800;
  font-size: 13.5px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.mk-gallery-meta {
  font-size: 12px;
  color: var(--text-3);
  margin-top: 3px;
}
.mk-gallery-badges { margin-top: 7px; display: flex; gap: 6px; flex-wrap: wrap; }
.mk-gallery-badge {
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 8px;
}
.mk-gallery-badge.mk-ok { color: #15803d; background: #f0fdf4; border-color: #bbf7d0; }
.mk-gallery-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  padding: 10px 12px 12px;
}

/* ---- the left toolkit rail ---------------------------------------------- */
.mk-rail {
  flex: 0 0 168px;
  width: 168px;
  padding: 10px;
  position: sticky;
  top: 12px;
}
.mk-rail-tabs {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 4px;
  margin-bottom: 10px;
}
.mk-rail-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 2px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: transparent;
  color: var(--text-2);
  font-size: 15px;
  cursor: pointer;
  min-width: 0;
}
.mk-rail-tab-k {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: uppercase;
  color: inherit;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mk-rail-tab.on {
  background: #0f172a;
  color: #fff;
  border-color: #0f172a;
}
.mk-rail-tab:hover:not(.on) { background: var(--surface-2, #f1f5f9); }
.mk-rail-h {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-3);
  margin: 4px 0 8px;
}
.mk-rail-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 9px;
  margin-bottom: 6px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: #fff;
  color: var(--text-1);
  font-size: 12.5px;
  font-weight: 600;
  text-align: start;
  cursor: pointer;
}
.mk-rail-btn:hover { border-color: #94a3b8; }
.mk-rail-glyph {
  flex: 0 0 22px;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--surface-2, #f1f5f9);
  font-size: 14px;
}
.mk-rail-glyph svg { width: 14px; height: 14px; }
.mk-rail-hint {
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
  margin: 6px 0 2px;
}
/* ── the rail's upload meter │───────────────────────────────────────────
   The picture itself goes to the server; this says how far. A spinner alone
   could not tell a 5 MB upload on a slow uplink apart from a stalled one. */
.mk-uprog { margin: 8px 0 4px; }
.mk-uprog-track {
  height: 7px; border-radius: 999px; overflow: hidden;
  background: var(--border, #e2e8f0);
}
.mk-uprog-fill {
  height: 100%; width: 0; border-radius: 999px;
  background: linear-gradient(90deg, #6366f1, #8b5cf6);
  transition: width .18s linear;
}
.mk-uprog-fill.is-done { background: #16a34a; }
.mk-uprog-meta {
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px; margin-top: 4px; font-size: 10.5px; color: var(--text-3);
}
/* No size reported: sweep, so it never looks frozen at 0%. */
.mk-uprog.is-indeterminate .mk-uprog-fill {
  width: 35%; animation: mk-uprog-sweep 1.1s ease-in-out infinite;
}
@keyframes mk-uprog-sweep {
  0% { margin-inline-start: -35%; }
  100% { margin-inline-start: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .mk-uprog.is-indeterminate .mk-uprog-fill {
    animation: none; width: 100%; opacity: .45;
  }
}
.mk-rail-icons {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
  margin-bottom: 6px;
  /* 127 marks would otherwise make the sticky rail taller than the window and
     the last rows would be unreachable: scroll INSIDE the grid instead. */
  max-height: 252px;
  overflow-y: auto;
  padding-right: 2px;
}
.mk-rail-icon[hidden] { display: none; }
.mk-rail-icon {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: #fff;
  color: #0f172a;
  cursor: pointer;
}
.mk-rail-icon:hover { border-color: #94a3b8; background: var(--surface-2, #f1f5f9); }
.mk-rail-icon svg { width: 18px; height: 18px; }
.mk-rail-thumbs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.mk-rail-thumb {
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
  cursor: pointer;
  aspect-ratio: 1 / 1;
}
.mk-rail-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- brand + background swatches ---------------------------------------- */
.mk-swatches { display: inline-flex; gap: 4px; vertical-align: middle; margin-inline-start: 6px; }
.mk-swatch {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 1px solid rgba(15, 23, 42, .22);
  padding: 0;
  cursor: pointer;
}
.mk-swatch:hover { transform: scale(1.08); }
.mk-bg-swatches { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 0 0; }
.mk-bg-swatch { width: 30px; height: 22px; border-radius: 7px; }
.mk-bg-swatch.on { outline: 2px solid #2563eb; outline-offset: 2px; }

/* ---- the three-step wizard ---------------------------------------------- */
.mk-wiz-veil {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(15, 23, 42, .55);
}
.mk-wiz {
  width: min(720px, 100%);
  max-height: min(88vh, 720px);
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, .35);
  overflow: hidden;
  /* The coupon chooser is an absolutely-positioned sheet INSIDE the wizard
     (`.mk-wiz-sheet { inset: 0 }`), so this has to be the containing block. */
  position: relative;
}
.mk-wiz-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.mk-wiz-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.mk-wiz-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
}
.mk-wiz-chip b {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--surface-2, #f1f5f9);
  font-size: 10.5px;
}
.mk-wiz-chip.on { border-color: #0f172a; color: var(--text-1); }
.mk-wiz-chip.on b { background: #0f172a; color: #fff; }
.mk-wiz-chip.done { color: #15803d; border-color: #bbf7d0; background: #f0fdf4; }
.mk-wiz-chip.done b { background: #15803d; color: #fff; }
.mk-wiz-body { padding: 16px; overflow: auto; flex: 1 1 auto; }
.mk-wiz-h { margin: 0 0 12px; font-size: 15px; font-weight: 800; }
.mk-wiz-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
}
.mk-wiz-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 12px;
  border: 1.5px solid var(--border);
  border-radius: 12px;
  background: #fff;
  text-align: start;
  cursor: pointer;
  font-size: 13px;
}
.mk-wiz-card:hover { border-color: #94a3b8; }
.mk-wiz-card.on { border-color: #2563eb; box-shadow: 0 0 0 2px rgba(37, 99, 235, .18); }
.mk-wiz-dims { font-weight: 800; font-size: 12px; color: var(--text-3); direction: ltr; }
.mk-wiz-note { font-size: 11.5px; color: var(--text-3); line-height: 1.4; }
.mk-wiz-tpl { align-items: stretch; }
.mk-wiz-art {
  width: 100%;
  height: auto;
  display: block;
  margin-bottom: 6px;
  border-radius: 6px;
  background: #fff;
}
.mk-wiz-bgs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}
.mk-wiz-bg {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border: 1.5px solid var(--border);
  border-radius: 12px;
  background: #fff;
  font-size: 12.5px;
  cursor: pointer;
  text-align: start;
}
.mk-wiz-bg.on { border-color: #2563eb; box-shadow: 0 0 0 2px rgba(37, 99, 235, .18); }
/* A shelf label inside a step ("Solid colours" / "Gradients"). */
.mk-wiz-sub {
  margin: 14px 0 8px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-3);
}
/* The wizard's picture shelf: every uploaded image is its own removable tile. */
.mk-wiz-imgs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}
.mk-wiz-img {
  position: relative;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
}
.mk-wiz-img img {
  display: block;
  width: 100%;
  height: 62px;
  object-fit: cover;
}
.mk-wiz-img figcaption {
  padding: 4px 6px;
  font-size: 10.5px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mk-wiz-imgx {
  position: absolute;
  top: 3px;
  inset-inline-end: 3px;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  border: 0;
  background: rgba(15, 23, 42, .72);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
}
.mk-wiz-imgx:hover { background: #b91c1c; }
/* The tiles live inside `.mk-wiz-up`, whose generic img rule (max-height 110px,
   a border) is for the OLD single-picture preview. The grid keeps its own
   uniform crop instead. */
.mk-wiz-up .mk-wiz-img img {
  max-width: none;
  max-height: none;
  height: 62px;
  border: 0;
  border-radius: 0;
  object-fit: cover;
}
/* The QR step's live preview. NO white backing: the code is generated on a
   transparent background and must look like part of the sheet. */
.mk-wiz-qr {
  width: 92px;
  height: 92px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: transparent;
  padding: 4px;
}
/* A QR that could not be made says WHY, here, next to the button — not in a toast
   that has already gone (and, outside the editor, used to not exist at all). */
.mk-wiz-qrerr {
  margin-top: 10px;
  padding: 8px 11px;
  border: 1px solid #fecaca;
  border-radius: 10px;
  background: #fef2f2;
  color: #b91c1c;
  font-size: 12px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.mk-wiz-bgchip {
  flex: 0 0 40px;
  width: 40px;
  height: 26px;
  border-radius: 7px;
  border: 1px solid rgba(15, 23, 42, .16);
}
.mk-wiz-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  background: var(--surface-2, #f8fafc);
}

/* A phone: the rail becomes a horizontal strip above the canvas. */
@media (max-width: 860px) {
  .mk-rail { flex: 1 1 100%; width: 100%; position: static; }
  .mk-rail-body { display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-start; }
  .mk-rail-btn { width: auto; }
  .mk-rail-h, .mk-rail-hint { flex: 1 1 100%; }
  .mk-rail-icons { grid-template-columns: repeat(10, 1fr); flex: 1 1 100%;
                   max-height: none; }
}

/* ---- a Marketing card's exported-file actions --------------------------- */
/* Three tiers on purpose, so the eye lands on the one action that matters:
     1. PDF — the primary: solid brand, full width, the only heavy control.
     2. The other export formats — one quiet group of outline buttons with
        SHORT labels; the full name and the byte size ride in the tooltip, so
        nothing has to be truncated to fit.
     3. View / Copy link / Share — borderless icon chips: they hand out a LINK,
        they do not download, so they must not look like a download.
   The band is tinted and separated from the design's story by a hairline, so a
   card reads as "artwork → story → files → the document's own actions". */
.mk-dl {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2, #f1f5f9), #fff 85%);
}
.mk-dl .btn,
.mk-row-files .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 0;
  min-height: 40px;
  padding: 6px 10px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.15;
  border-radius: var(--r-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-decoration: none;
  transition: background .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.mk-dl .btn { width: 100%; }
/* THE action: the only solid button on the card, and the only one that lifts. */
.mk-dl .btn.mk-dl-main {
  width: 100%;
  box-shadow: var(--shadow-brand);
}
.mk-dl .btn.mk-dl-main:hover { box-shadow: 0 10px 22px rgba(79, 70, 229, .34); }
.mk-dl .mk-dl-sz {
  opacity: .72; font-weight: 500; font-size: 11px;
  white-space: nowrap;   /* "1.7 MB" must never break into two lines */
}

/* Tier 2: equal cells, so the three formats read as one group rather than three
   competing buttons. PNG takes the whole last line on a narrow card. */
.mk-dl-alt {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.mk-dl-alt .btn {
  min-height: 34px;
  padding: 4px 6px;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-2);
  background: #fff;
  border: 1px solid var(--border-2);
  box-shadow: none;
}
.mk-dl-alt .btn:hover {
  background: var(--brand-50);
  border-color: var(--brand-400);
  color: var(--brand-600);
}

/* Tier 3: chips, not buttons — no label, no fill, a hairline box so the icon
   reads as something you can press. They answer with their name on hover
   (`title`) and to a screen reader (`aria-label`). */
.mk-dl-tools {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.mk-dl-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 38px;
  width: 38px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .7);
  color: var(--text-2);
  font-family: inherit;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.mk-dl-ico:hover {
  background: #fff;
  border-color: var(--brand-300);
  color: var(--brand-600);
}
.mk-dl-ico:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 1px; }
/* A text glyph (not an emoji) is drawn by the FONT, so it sits small and thin
   next to the emoji chips: it needs a size and a colour of its own to read as
   "copy" at all. */
.mk-dl-ico.mk-dl-ico-glyph {
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
}

/* A narrow card: the labels come off, the sizes go into the tooltips, and the
   formats fall back to two per line. */
@media (max-width: 560px) {
  .mk-dl { padding: 8px 10px 10px; gap: 6px; }
  .mk-dl .mk-dl-sz { display: none; }
  .mk-dl-alt { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mk-dl-alt .mk-dl-alt-png { grid-column: 1 / -1; }
}

/* ---- Edit / Delete: the design's own actions, in their own footer -------- */
/* Under a hairline, below the downloads: Edit is the theme's OUTLINE button and
   Delete is quiet red TYPE that only fills in on hover. Neither is solid, so
   neither competes with the download — and Delete, the only destructive control
   on the card, reads last. */
.mk-doc-foot {
  display: flex;
  align-items: stretch;
  gap: 8px;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--border);
}
.mk-design-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 38px;
  padding: 0 14px;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  border-radius: var(--r-sm);
  cursor: pointer;
  white-space: nowrap;
}
.mk-doc-foot .mk-edit { flex: 1 1 auto; }
.mk-doc-foot .mk-del {
  flex: 0 0 auto;
  background: transparent;
  border: 1px solid transparent;
}
.mk-del { color: #b91c1c; }
.mk-del:hover:not(:disabled) { background: #fef2f2; border-color: #fca5a5; color: #b91c1c; }

/* The admin template gallery still stacks its two actions (it has no file band,
   so the card there is "thumbnail → title → one action"). */
.mk-gallery-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 12px 12px;
}

/* ---- the shelf's toolbar: search, sort, cards/list ----------------------- */
.mk-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 0 0 14px;
}
.mk-search {
  flex: 1 1 220px;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 10px;
  border: 1px solid var(--border-2);
  border-radius: 10px;
  background: #fff;
}
.mk-search span { font-size: 13px; opacity: .6; }
.mk-search .input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  padding: 9px 0;
  font: inherit;
  font-size: 13px;
}
.mk-sort { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-3); font-weight: 600; }
.mk-sort .input { padding: 7px 8px; font-size: 12.5px; border-radius: 9px; }
.mk-views { display: flex; gap: 4px; margin-inline-start: auto; }
.mk-views .btn { min-width: 38px; justify-content: center; }
.mk-count {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-3);
  background: var(--surface-2, #f1f5f9);
  border-radius: 999px;
  padding: 2px 8px;
  margin-inline-start: 6px;
  vertical-align: middle;
}

/* ---- the shelf's LIST view ---------------------------------------------- */
/* THREE columns, not four: the thumb, the design's story, and the actions in a
   fixed cluster at the end behind a divider. The story column takes the leftover
   width and CLIPS inside itself, so a Persian name or a long meta line can no
   longer escape its column and paint across the buttons — the old
   `[thumb][1.1fr][1.4fr][140px]` grid gave the buttons 1.4fr, squeezed the story
   to a sliver and let it spill out. */
/* The shelf is a CONTAINER, not a viewport: a row's actions have to adapt to the
   width of the panel they sit in (a sidebar takes ~230 px off the window), so
   the breakpoints below measure the list, not the screen. */
.mk-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  container-type: inline-size;
  container-name: mkshelf;
}
.mk-row {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  padding: 10px 12px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.mk-row-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60px;
  padding: 4px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface-2, #f1f5f9);
  cursor: pointer;
  overflow: hidden;
}
.mk-row-thumb img { max-width: 100%; max-height: 52px; background: #fff; box-shadow: 0 2px 8px rgba(15, 23, 42, .16); }
.mk-row-main { min-width: 0; overflow: hidden; }
.mk-row .mk-gallery-title { -webkit-line-clamp: 1; }
.mk-row .mk-gallery-meta { margin-top: 2px; }
.mk-row .mk-gallery-badges { margin-top: 5px; flex-wrap: nowrap; overflow: hidden; }

/* The actions keep their own width (`auto`, never a fraction of the row) and are
   fenced off from the story by a hairline — the divider the card has too. */
.mk-row-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-inline-start: 12px;
  border-inline-start: 1px solid var(--border);
}
.mk-row-files { display: flex; align-items: center; gap: 6px; }
/* The primary keeps its label (it is still THE action), just smaller. */
.mk-row-files > .btn.mk-dl-main {
  width: auto;
  min-height: 34px;
  padding: 5px 12px;
  font-size: 12px;
  box-shadow: none;
}
/* Tier 2 and 3 are icon chips here: a row cannot carry six labels. */
.mk-row-files .mk-dl-alt { display: flex; align-items: center; gap: 4px; }
.mk-row-files .mk-dl-alt .btn {
  width: 32px;
  min-height: 32px;
  padding: 0;
  font-size: 14px;
}
.mk-row-files .mk-dl-tools { gap: 2px; }
.mk-row-files .mk-dl-ico { flex: 0 0 30px; width: 30px; height: 30px; font-size: 13px; }
.mk-row-acts { display: flex; align-items: center; gap: 4px; }
.mk-row-acts .mk-design-btn {
  min-height: 30px;
  width: 30px;
  padding: 0;
  font-size: 13px;
}
/* Delete is a chip here too: no fill, no border, red only where it can be seen. */
.mk-row-acts .mk-del { background: transparent; border-color: transparent; }

/* ---- the next page ------------------------------------------------------- */
.mk-more { display: flex; justify-content: center; margin: 16px 0 4px; }
.mk-next { min-width: 220px; justify-content: center; }
.mk-end { font-size: 12.5px; color: var(--text-3); }

@media (max-width: 560px) {
  /* A phone: the actions leave the line even if the container query above does
     not run (a browser too old for `@container` still gets this). */
  .mk-row { grid-template-columns: 56px minmax(0, 1fr); }
  .mk-row-thumb { height: 48px; }
}

@container mkshelf (max-width: 760px) {
  /* A narrow shelf: the actions have nowhere to go beside the story, so they
     take their own line and the divider turns with them. */
  .mk-row { grid-template-columns: 60px minmax(0, 1fr); }
  .mk-row-thumb { height: 52px; }
  .mk-row-actions {
    grid-column: 1 / -1;
    flex-wrap: wrap;
    padding-inline-start: 0;
    padding-top: 10px;
    border-inline-start: 0;
    border-top: 1px solid var(--border);
  }
}

/* ---- wizard step 4: the content form ------------------------------------- */
.mk-wiz-create-row { display: flex; gap: 8px; flex-wrap: wrap; }
.mk-wiz-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
  min-width: 0;
}
.mk-wiz-field > span {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-2);
}
.mk-wiz-field .input {
  width: 100%;
  padding: 9px 11px;
  font: inherit;
  font-size: 13px;
  border: 1px solid var(--border-2);
  border-radius: 10px;
  background: #fff;
}
.mk-wiz-field textarea.input { resize: vertical; min-height: 64px; line-height: 1.45; }
.mk-wiz-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.mk-wiz-up {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}
.mk-wiz-up img {
  max-width: 100%;
  max-height: 110px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: #fff;
}
.mk-wiz-upbtn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 12px;
  border: 1px dashed var(--border-2);
  border-radius: 10px;
  background: #fff;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-2);
  cursor: pointer;
}
.mk-wiz-upbtn:hover { border-color: var(--brand-300, #a5b4fc); background: var(--brand-50, #eef2ff); }
/* The two doors side by side: a file from this machine, or one already in the
   Media Library. They wrap on a narrow wizard rather than shrink to nothing. */
.mk-wiz-upbtns {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.mk-wiz-upbtns .mk-wiz-upbtn { white-space: nowrap; }
.mk-wiz-check {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
  padding: 9px 0;
}
.mk-wiz-check input { width: 16px; height: 16px; accent-color: var(--brand-600); }

/* the coupon pill box */
.mk-wiz-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.mk-wiz-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 10px;
  border: 1px solid var(--brand-300, #a5b4fc);
  border-radius: 999px;
  background: var(--brand-50, #eef2ff);
  color: var(--brand-700, #4338ca);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .01em;
}
.mk-wiz-pill button {
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 11px;
  line-height: 1;
  padding: 2px 4px;
  cursor: pointer;
  opacity: .7;
}
.mk-wiz-pill button:hover { opacity: 1; }
.mk-wiz-addpill { border-radius: 999px; }
.mk-wiz-ainote {
  border-left: 3px solid var(--brand-400, #818cf8);
  padding: 6px 10px;
  background: var(--brand-50, #eef2ff);
  border-radius: 0 8px 8px 0;
  color: var(--text-2);
}

/* the coupon chooser — a sheet inside the wizard */
.mk-wiz-sheet {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(15, 23, 42, .42);
  border-radius: 16px;
}
.mk-wiz-sheet-in {
  width: 100%;
  max-height: 72%;
  overflow: auto;
  background: #fff;
  border-radius: 16px 16px 0 0;
  padding: 12px 14px 14px;
  box-shadow: 0 -12px 34px rgba(15, 23, 42, .28);
}
.mk-wiz-sheet-head,
.mk-wiz-sheet-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.mk-wiz-sheet-head { margin-bottom: 8px; }
.mk-wiz-sheet-foot { margin-top: 10px; }
.mk-wiz-couponlist { display: flex; flex-direction: column; gap: 6px; }
.mk-wiz-coupon {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  text-align: start;
  padding: 9px 11px;
  border: 1px solid var(--border-2);
  border-radius: 10px;
  background: #fff;
  cursor: pointer;
  font: inherit;
}
.mk-wiz-coupon b { font-size: 13px; letter-spacing: .04em; }
.mk-wiz-coupon span { font-size: 12px; color: var(--text-2); }
.mk-wiz-coupon i { font-size: 11px; color: var(--text-3); font-style: normal; margin-inline-start: auto; }
.mk-wiz-coupon:hover { border-color: var(--brand-300, #a5b4fc); }
.mk-wiz-coupon.on {
  border-color: var(--brand-500, #6366f1);
  background: var(--brand-50, #eef2ff);
  box-shadow: inset 0 0 0 1px var(--brand-500, #6366f1);
}

@media (max-width: 560px) {
  .mk-wiz-pair { grid-template-columns: 1fr; }
  .mk-wiz-create-row { flex-direction: column-reverse; }
  .mk-wiz-create-row .btn { width: 100%; justify-content: center; }
}
