/* CampaignDock — design system. Native CSS: cascade layers, nesting, OKLCH. */
@layer tokens, base, layout, components;

@layer tokens {
  :root {
    /* Surfaces */
    --page: oklch(0.9761 0.0041 91.4);   /* #F8F7F4 */
    --sidebar: oklch(0.9468 0.0086 84.6); /* #F0EDE7 */
    --card: oklch(1 0 0);                 /* #FFFFFF */
    --inset: oklch(0.9913 0.0029 84.6);   /* #FDFCFA */

    /* Lines */
    --border: oklch(0.8906 0.0138 78.3);  /* #E0DAD1 */
    --border2: oklch(0.9178 0.0109 76.6); /* #E8E3DC */
    --hairline: oklch(0.9624 0.0062 75.4);/* #F5F2EE */

    /* Text */
    --ink: oklch(0.2193 0.0050 67.6);     /* #1C1A18 */
    --soft: oklch(0.5051 0.0200 84.6);    /* #6A6458 */
    --muted: oklch(0.6151 0.0191 84.6);   /* #8A8478 */
    --dim: oklch(0.7102 0.0148 67.6);     /* #A8A098 */
    --label: oklch(0.7338 0.0243 84.6);   /* #B0A898 */

    /* Accent */
    --accent: oklch(0.4941 0.1841 270.5);     /* #3D52C8 */
    --accent-soft: oklch(0.9548 0.0170 267.8);/* #EBF0FC */
    --accent-ink: oklch(0.4271 0.1812 269.5); /* #2B3EB0 */
    --accent-nav: oklch(0.9445 0.0206 274.0); /* #E8ECFB */
    --accent-tint: oklch(0.9714 0.0107 268.4); /* #F2F5FD — palest blue, glyph tiles */
    --accent-border: oklch(0.8694 0.0486 271.2); /* #C8D3F5 */

    /* Video panel darks */
    --vid-0: oklch(0.2000 0.0137 94.0);  /* #18160F */
    --vid-1: oklch(0.1812 0.0193 98.4);  /* #141208 */
    --vid-2: oklch(0.2453 0.0157 84.5);  /* #242018 */
    --vid-3: oklch(0.2680 0.0146 95.6);  /* #28261E */
    --vid-4: oklch(0.2925 0.0143 95.5);  /* #2E2C24 */
    --vid-ink: oklch(0.5143 0.0245 101.3);/* #6A6858 */

    /* Status */
    --badge-amber: oklch(0.6614 0.1113 68.9); /* #B8862E — nav/badge counts */
    --icon-tile: oklch(0.9556 0.0075 84.6);   /* #F4F1EB — menu-sheet icon tiles */
    --chevron: oklch(0.7801 0.0155 67.6);     /* #C0B8AE — row chevrons */
    --ok: oklch(0.5688 0.1165 150.9);    /* #3A8A52 */
    /* Tint + strong pairs for delta/status treatments (text-on-tint). The four
       semantic status tints (bg / ink / dot) reuse these: green=ok-*, danger=err-*,
       amber=the two below + badge-amber dot, neutral=sidebar/soft/dim. */
    --ok-tint: #E4F3EC;   --ok-strong: #1E7A52;
    --err-tint: #F9E9E5;  --err-strong: #A63722;
    --amber-tint: #F6EEDD; --amber-ink: #8A6220;
    --warn: oklch(0.6242 0.1583 46.8);   /* #B5502D */
    --err: oklch(0.5495 0.1974 25.4);    /* #C0392B */
    --on-accent: oklch(0.9761 0.0041 91.4);

    --r-sm: 5px;
    --r: 6px;
    --r-md: 8px;
    --r-lg: 10px;
    --r-xl: 14px;
    --r-tile: 12px;  /* icon tiles, inset panels, stat grid */
    --r-card: 16px;  /* cards */
    --shadow-sm: 0 1px 2px oklch(0.22 0.005 68 / 0.05);
    --mono: ui-monospace, "SF Mono", Menlo, monospace;
  }

  @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
  @keyframes slideIn { from { transform: translateX(100%); } to { transform: translateX(0); } }
  @keyframes toast {
    0% { opacity: 0; transform: translate(-50%, 8px); }
    8%, 88% { opacity: 1; transform: translate(-50%, 0); }
    100% { opacity: 0; transform: translate(-50%, 8px); }
  }
}

@layer base {
  * { box-sizing: border-box; }

  body {
    margin: 0;
    background: var(--page);
    color: var(--ink);
    font-family: "Figtree", system-ui, sans-serif;
    -webkit-font-smoothing: antialiased;
  }

  button, input, select, textarea { font-family: inherit; }

  a { color: var(--accent); text-decoration: none; }

  /* Shared button system */
  .btn {
    border: none;
    border-radius: var(--r);
    padding: 8px 15px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: -0.01em;
    cursor: pointer;
    background: transparent;
  }
  .btn-primary { background: var(--accent); color: var(--on-accent); }
  .btn-dark { background: var(--ink); color: var(--on-accent); }
  .btn-outline { border: 1.5px solid var(--ink); color: var(--ink); border-radius: var(--r-md); padding: 10px 22px; font-size: 13px; }
  .btn-ghost { border: 1px solid var(--border2); color: var(--muted); }
  .btn-sm { padding: 5px 11px; font-size: 11px; }
  .btn-lg { padding: 10px 22px; font-size: 13px; border-radius: var(--r-md); }

  .section-label {
    font-size: 9px;
    font-weight: 600;
    color: var(--label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }
}

@layer layout {
  .app { display: flex; height: 100vh; overflow: hidden; }
  .main { flex: 1; position: relative; overflow: hidden; }

  .view { position: absolute; inset: 0; overflow-y: auto; animation: fadeIn 0.12s ease; }
  .view--column { display: flex; flex-direction: column; }

  .flash { margin: 0; padding: 10px 16px; font-size: 13px; }
  .flash--notice { color: var(--ok); }
  .flash--alert { color: oklch(0.55 0.2 25); }
}

@layer components {
  /* ── Sidebar ─────────────────────────────────────── */
  .sidebar {
    width: 236px;
    min-width: 236px;
    background: var(--sidebar);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;

    & .sidebar-brand {
      display: flex; align-items: center; gap: 9px;
      padding: 20px 18px 14px; border-bottom: 1px solid var(--border); font-size: 13px; font-weight: 700; letter-spacing: -0.02em;

      & img { display: block; }
    }
  }

  .client-select {
    width: 100%;
    padding: 7px 9px;
    border: 1px solid var(--border);
    border-radius: var(--r);
    font-size: 12px;
    font-weight: 500;
    color: var(--ink);
    background: var(--card);
    cursor: pointer;
  }

  .nav { flex: 1; padding: 14px 12px; overflow-y: auto; display: flex; flex-direction: column; gap: 3px; }

  .nav-item {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    padding: 10px 12px;
    border-radius: var(--r-lg);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--soft);
    cursor: pointer;
    border: none;
    background: transparent;
    text-align: left;

    &:hover { background: oklch(0.92 0.008 84.6); }
    &.is-active { background: var(--card); color: var(--accent); box-shadow: var(--shadow-sm); }
    &.is-disabled { color: oklch(0.78 0.012 80); cursor: not-allowed; }
    &:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
    & .count-badge { margin-left: auto; }
  }

  /* A labelled group inside the rail. It has to re-declare the nav's own column+gap: as a
     flex child of .nav it is one item, so its links would otherwise stack with no spacing.
     No divider rule — the heading's 16px top padding is the whole separator. */
  .nav-group { display: flex; flex-direction: column; gap: 3px; }
  .nav-group .section-label { display: block; padding: 16px 10px 8px; }

  .sidebar-user { padding: 12px; border-top: 1px solid var(--border); }
  .user-menu { position: relative; }
  .user-menu > summary { list-style: none; cursor: pointer; }
  .user-menu > summary::-webkit-details-marker { display: none; }
  .sidebar-user .user-row {
    display: flex; align-items: center; gap: 11px; padding: 9px 12px; border-radius: var(--r-lg);

    &:hover { background: oklch(0.92 0.008 84.6); }
    &.is-active { background: var(--card); box-shadow: var(--shadow-sm); }
  }
  .user-menu[open] > .user-row { background: var(--card); box-shadow: var(--shadow-sm); }
  .sidebar-user .user-meta { flex: 1; min-width: 0; }
  .sidebar-user .name { font-size: 13px; font-weight: 600; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sidebar-user .email { font-size: 11px; color: var(--dim); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sidebar-user .user-caret { color: var(--dim); flex-shrink: 0; transition: transform 0.15s ease; }
  .user-menu[open] .user-caret { transform: rotate(180deg); }

  .user-options {
    position: absolute; left: 0; right: 0; bottom: 100%; margin-bottom: 8px; z-index: 40;
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-xl);
    box-shadow: 0 8px 24px oklch(0.2 0 0 / 0.14); padding: 6px;
  }
  .user-options form { margin: 0; }
  .user-option {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 11px; border-radius: 9px;
    font-size: 13px; font-weight: 500; color: var(--ink); background: none; border: none; cursor: pointer; text-align: left;

    &:hover { background: var(--sidebar); }
    &.is-destructive { color: var(--err-strong); }
    &.is-destructive:hover { background: var(--err-tint); }
  }
  .user-menu-divider { height: 1px; background: var(--hairline); margin: 5px 8px; }

  /* Reusable count badge — nav rail, mobile tabs, and anywhere a small tally
     rides an item. Amber pill; the --tab variant sits on a mobile icon. */
  .count-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
    background: var(--badge-amber); color: #fff; font-size: 10px; font-weight: 700; line-height: 1;
  }
  .count-badge--tab {
    position: absolute; top: -3px; right: 6px;
    min-width: 16px; height: 16px; padding: 0 4px; font-size: 9.5px; border: 2px solid var(--card);
  }

  .avatar {
    width: 26px; height: 26px; border-radius: 50%;
    background: var(--border);
    display: flex; align-items: center; justify-content: center;
    font-size: 9.5px; font-weight: 600; color: var(--muted);
    flex-shrink: 0;
    overflow: hidden;
  }
  .avatar img, .person-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }

  /* ── Tool header ── */
  /* The page header bar, built to its own front-end brief and shared by every full-app
     page: 32px tint tile + icon, 15px h1, 11.5px subtitle, pill actions on the right.
     Pages differ only in their furniture — a tile means "section home", a .tool-back circle
     means "one level in"; subtitles, tab chips and the outbox button are per-page. */
  .tool-header {
    padding: 16px 24px;
    min-height: 64px;
    border-bottom: 1px solid var(--border2);
    background: var(--card);
    display: flex; align-items: center; justify-content: space-between; gap: 20px;
    flex-shrink: 0;

    /* Ring whatever is focusable, rather than listing classes: some header actions
       (.tool-back, for one) aren't .btn, and the next one won't be either. */
    & :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  }
  /* The "one level in" circle from the comment above. 32px to match .tool-badge, so the
     title doesn't shift when you move between a section home and a page inside it. */
  .tool-back {
    width: 32px; height: 32px; border-radius: 50%; flex: none;
    background: var(--hairline); color: var(--soft);
    display: grid; place-items: center;
    &:hover { background: var(--border2); color: var(--ink); }
  }
  .tool-header .title-group { display: flex; align-items: center; gap: 13px; min-width: 0; }
  /* The middle of the flex chain is an unclassed wrapper div on 5 of the pages. Without
     min-width:0 an over-long title can't ellipsis — it shoves the button out of the bar. */
  .tool-header .title-group > * { min-width: 0; }
  .tool-header .title {
    font-size: 15px; font-weight: 700; letter-spacing: -0.02em;
    margin: 0; /* it's an <h1>; the UA's .67em would grow every bar by ~20px */
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .tool-badge {
    width: 32px; height: 32px; background: var(--accent-soft); color: var(--accent);
    border-radius: var(--r-lg); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  }

  /* ── Video Clipper ───────────────────────────────── */
  .clipper { flex: 1; display: grid; grid-template-columns: 1fr 288px; min-height: 0; }

  .player { display: flex; flex-direction: column; background: var(--vid-0); border-right: 1px solid var(--border2); }
  .player-stage { flex: 1; display: flex; align-items: center; justify-content: center; min-height: 0; padding: 16px; }
  .player-stage video { max-width: 100%; max-height: 100%; }
  .player-stage:has(video[src]) .player-empty { display: none; }
  .player-empty { text-align: center; user-select: none; color: var(--vid-3); }
  .player-empty .icon { width: 44px; height: 44px; background: var(--vid-2); border-radius: var(--r-lg); display: flex; align-items: center; justify-content: center; margin: 0 auto 12px; }
  .player-empty .label { font-size: 12px; color: oklch(0.36 0.012 90); font-weight: 500; }

  .player-controls { padding: 14px 20px 18px; border-top: 1px solid var(--vid-3); background: var(--vid-1); flex-shrink: 0; }
  .timecode { display: flex; align-items: center; justify-content: space-between; margin-bottom: 7px; }
  .timecode span { font-size: 10px; font-family: var(--mono); letter-spacing: 0.05em; color: var(--vid-ink); }
  .scrubber { height: 3px; background: var(--vid-3); border-radius: 2px; margin-bottom: 14px; }
  .scrubber-fill { height: 100%; background: var(--accent); border-radius: 2px; }
  .player-buttons { display: flex; align-items: center; justify-content: center; gap: 7px; }
  .player-buttons .btn-ghost { border-color: var(--vid-4); color: var(--vid-ink); background: transparent; }

  .frames-panel { display: flex; flex-direction: column; background: var(--card); min-height: 0; }
  .frames-head { padding: 13px 16px 11px; border-bottom: 1px solid var(--border2); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; }
  .frames-head .title { font-size: 12px; font-weight: 600; }
  .frames-head .count { font-size: 10.5px; color: var(--dim); margin-top: 1px; }
  .frames-list { flex: 1; overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 7px; }

  .frame-row {
    display: flex; align-items: center; gap: 9px; padding: 8px;
    border: 1px solid var(--border2); border-radius: 7px; background: var(--inset);

    & .frame-thumb { width: 70px; height: 39px; border-radius: 4px; flex-shrink: 0; object-fit: cover; background: repeating-linear-gradient(-45deg, var(--vid-0), var(--vid-0) 3px, var(--vid-2) 3px, var(--vid-2) 6px); }
    & .frame-body { flex: 1; min-width: 0; }
    & .frame-name { font-size: 11px; font-weight: 600; }
    & .frame-time { font-size: 9.5px; color: var(--dim); font-family: var(--mono); margin-top: 2px; }
    & textarea { width: 100%; border: 1px solid var(--border2); border-radius: var(--r-sm); padding: 4px 6px; font-size: 11px; resize: vertical; color: var(--ink); background: var(--inset); margin-top: 4px; }
    & form { margin: 0; flex: 1; min-width: 0; }
  }

  /* Shared empties + hints + copy feedback */
  .empty-state { padding: 22px; text-align: center; font-size: 12px; color: var(--muted); }
  .hint { font-size: 12px; color: var(--muted); margin: 6px 0; }
  .copied { color: var(--ok) !important; }

  /* ── Campaigns ───────────────────────────────────── */
  .campaigns-subtitle { font-size: 11.5px; color: var(--dim); margin-top: 2px; }
  .campaigns-header-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
  /* Every header action is a pill; the single primary carries the brand-blue glow. The
     brief is explicit that hover darkens the fill and nothing else — no lift, no growth. */
  .tool-header .btn {
    display: inline-flex; align-items: center; gap: 8px;
    border-radius: 999px; padding: 10px 20px; font-size: 13px; transition: background 0.12s ease;
    /* The action never compresses — the title truncates first (that's what the
       min-width:0 chain on .title-group is for). */
    white-space: nowrap; flex-shrink: 0;
  }
  .tool-header .btn-primary { box-shadow: 0 4px 14px oklch(0.4941 0.1841 270.5 / 0.26); }
  .tool-header .btn-primary:hover { background: var(--accent-ink); }
  .btn-queued { display: inline-flex; align-items: center; gap: 7px; }

  .campaigns-body { flex: 1; overflow: auto; padding: 0 24px 40px; background: var(--page); }

  /* Controls row (agency): search + client/status filter menus. */
  .campaigns-controls { display: flex; align-items: center; gap: 12px; padding: 16px 0 12px; }

  /* Card-wrapped table. overflow stays VISIBLE — a clip context (even overflow-x:auto
     forces overflow-y:auto) would crop the status/filter dropdowns that open below a
     row. The rounded look comes from the border-radius here + rounding the corner
     header/last cells so their backgrounds don't poke past the border. */
  .campaigns-table-wrap {
    overflow: visible; background: var(--card); border: 1px solid var(--border2);
    border-radius: var(--r-card); box-shadow: var(--shadow-sm);
  }
  /* border-collapse: separate is load-bearing — collapsed tables ignore cell
     border-radius, so the corner cells couldn't round and their square bg poked
     past the wrap's rounded border (overflow must stay visible for dropdowns).
     Separated borders let the corner cells round; dividers all live on the row's
     TOP edge, so a group separator is just a darker recolor of that one border. */
  .campaigns-table { width: 100%; min-width: 860px; border-collapse: separate; border-spacing: 0; }
  .campaigns-table th {
    text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--label); padding: 13px 12px; white-space: nowrap;
  }
  .campaigns-table thead tr { background: var(--page); }
  .campaigns-table thead th { border-bottom: 1px solid var(--border2); }
  .campaigns-table thead th:first-child { border-top-left-radius: var(--r-card); }
  .campaigns-table thead th:last-child { border-top-right-radius: var(--r-card); }
  .campaigns-table tbody tr:last-child td:first-child { border-bottom-left-radius: var(--r-card); }
  .campaigns-table tbody tr:last-child td:last-child { border-bottom-right-radius: var(--r-card); }
  .campaigns-table tbody td { border-top: 1px solid var(--hairline); }
  .campaigns-table tbody tr:first-child td { border-top: none; }
  .campaigns-table td { padding: 14px 12px; font-size: 12.5px; vertical-align: middle; white-space: nowrap; }
  .campaigns-table th:first-child, .campaigns-table td:first-child { padding-left: 20px; }
  .campaigns-table th:last-child, .campaigns-table td:last-child { padding-right: 20px; }
  .campaigns-count { font-size: 11.5px; color: var(--dim); margin-top: 14px; }
  /* Zebra by client group (set server-side in campaigns/_campaign): even groups
     white, odd groups a whisper of warm grey. Hover is darker than both tints so
     it still reads on grey rows. Color is reserved for the status pill. */
  .campaigns-table tbody tr.campaign-row { background: #FFFFFF; }
  .campaigns-table tbody tr.campaign-row--alt { background: #F8F5EF; }
  .campaigns-table tbody tr:hover { background: #EFEAE1; }
  .campaigns-table .campaign-name { font-weight: 700; }
  .campaigns-table .campaign-last-update { color: var(--soft); font-size: 11px; }
  .campaign-row { cursor: pointer; }
  .campaign-name a { color: var(--ink); text-decoration: none; }
  .kpi-soon { color: var(--dim); font-size: 10.5px; font-style: italic; }

  /* ── Search pill + column filter menus (dashboard + approvals) ── */
  .search-pill {
    display: flex; align-items: center; gap: 10px; margin: 0;
    background: var(--card); border: 1px solid var(--border); border-radius: 999px;
    padding: 10px 18px; width: 240px; color: var(--dim);
  }
  .search-pill input {
    border: none; background: transparent; outline: none; font-size: 13px; color: var(--ink);
    width: 100%; padding: 0;
  }
  .search-pill input::placeholder { color: var(--dim); }

  .filter-menu { position: relative; display: inline-block; }
  .filter-menu > summary { list-style: none; cursor: pointer; }
  .filter-menu > summary::-webkit-details-marker { display: none; }
  .filter-pill {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--card); border: 1px solid var(--border); border-radius: 999px;
    padding: 9px 16px; font-size: 13px; font-weight: 600; color: var(--soft);
    transition: border-color 0.12s ease, background 0.12s ease;
  }
  .filter-pill:hover { border-color: var(--label); background: var(--page); }
  .filter-pill.is-active { color: var(--accent-ink); border-color: var(--accent-border); background: var(--accent-soft); }
  .filter-th {
    display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
    font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  }
  .filter-th.is-active { color: var(--accent); }
  .filter-caret { opacity: 0.55; flex-shrink: 0; }

  /* The popover shell, shared by the filter/sort menus, the share panel (.share-pop, in the
     Creative Set block) and a table row's ⋯ menu — each variant owns only its edge, width
     and spacing. */
  .filter-options, .share-pop, .row-menu-pop {
    position: absolute; top: calc(100% + 6px); z-index: 30;
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-tile);
    box-shadow: 0 12px 30px oklch(0.22 0.005 68 / 0.16);
    display: flex; flex-direction: column;
  }
  .filter-options { left: 0; padding: 6px; min-width: 214px; gap: 1px; }

  /* A row's ⋯ menu. Right-anchored because it hangs off the last column, and it opens
     inside a <details>, which row_link already treats as "not a click on the row". */
  /* Sits at the far end of its cell, not tacked onto the timestamp — so the ⋯ column lines
     up down the table and reads as a control rather than as more text. */
  .campaign-last-update:has(.row-menu) { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
  .row-menu { position: relative; flex-shrink: 0; }
  .row-menu > summary { list-style: none; cursor: pointer; }
  .row-menu > summary::-webkit-details-marker { display: none; }
  .row-menu-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 6px; color: var(--label);
  }
  .row-menu-btn:hover { background: var(--hairline); color: var(--ink); }
  .row-menu-pop { right: 0; padding: 6px; min-width: 160px; gap: 1px; }
  .row-menu-item {
    padding: 8px 10px; border-radius: 6px; font-size: 12.5px; font-weight: 600;
    color: var(--ink); text-decoration: none;
  }
  .row-menu-item:hover { background: var(--hairline); }
  .th-filter .filter-options { text-transform: none; letter-spacing: normal; }
  .filter-options-head { padding: 8px 10px 6px; }
  .filter-option {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 8px 10px; border-radius: var(--r-md); font-size: 13px; font-weight: 500; color: var(--ink);
  }
  .filter-option:hover { background: var(--page); }
  .filter-option.is-active { color: var(--accent-ink); font-weight: 600; }
  .filter-check { color: var(--accent); }

  /* Segmented count-pill filter (approvals Active/Approved/All) — active = blue tint. */
  .seg-filter {
    display: inline-flex; gap: 4px; margin-left: auto; background: var(--card);
    border: 1px solid var(--border2); border-radius: 14px; padding: 5px; box-shadow: var(--shadow-sm);
  }
  .seg {
    display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 10px;
    font-size: 12.5px; font-weight: 600; color: var(--soft);
  }
  .seg.is-active { background: var(--accent-soft); color: var(--accent-ink); }
  .seg-count {
    font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px;
    background: var(--sidebar); color: var(--dim);
  }
  .seg.is-active .seg-count { background: #DDE6FB; color: var(--accent-ink); }

  /* Board sortable column headers. */
  .cs-sort { display: inline-flex; align-items: center; gap: 4px; color: var(--label); cursor: pointer; }
  .cs-sort:hover { color: var(--soft); }
  .cs-sort.is-active { color: var(--accent); }

  /* "N approved sets hidden" footer — the last child inside the card (Active filter).
     Its own border-top is the divider; it rounds the card's bottom, so the last table
     row drops its bottom rounding when the footer is present. */
  .cs-hidden-foot {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 14px 22px; font-size: 12.5px; font-weight: 600; color: var(--soft);
    background: #FBFAF8; border-top: 1px solid var(--hairline);
    border-radius: 0 0 var(--r-card) var(--r-card);
  }
  .cs-hidden-foot:hover { background: #F3F0EB; }
  .cs-hidden-show { margin-left: auto; color: var(--accent); }
  .campaigns-table-wrap:has(.cs-hidden-foot) .campaigns-table tbody tr:last-child td { border-radius: 0; }

  /* Striped "coming soon" budget bar */
  .budget-bar {
    height: 8px; border-radius: 999px; overflow: hidden;
    background: repeating-linear-gradient(45deg, #E7E1D8, #E7E1D8 4px, #F0ECE6 4px, #F0ECE6 8px);
  }
  .budget-bar--sm { width: 64px; margin-top: 5px; }

  /* Generic stat label/value (perf module + portal; portal overrides below) */
  .stat-label { font-size: 9px; font-weight: 600; color: var(--label); letter-spacing: 0.08em; text-transform: uppercase; }
  .stat-value { font-size: 15px; font-weight: 700; color: var(--ink); margin-top: 4px; }

  /* ── Client portal cards ─────────────────────────── */
  /* Portal header (client Campaigns view) shares the 920px column with the cards. */
  /* One rule, not two: these used to be equal-specificity selectors whose padding fought
     on source order alone. Only campaigns#index ever carries .portal. */
  .view.portal .tool-header {
    background: transparent; border-bottom: none;
    max-width: 920px; margin: 0 auto; width: 100%; padding: 32px 32px 8px;
  }
  .view.portal .tool-header .title { font-size: 26px; font-weight: 800; letter-spacing: -0.04em; line-height: 1; }
  .view.portal .campaigns-subtitle { font-size: 13.5px; color: var(--muted); margin-top: 8px; line-height: 1.5; }

  .portal-cards { max-width: 920px; margin: 0 auto; padding: 16px 32px 48px; display: flex; flex-direction: column; gap: 16px; }
  .portal-card {
    display: block; background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); overflow: hidden; padding: 24px 24px 20px; text-decoration: none; color: inherit;
    transition: transform 0.12s ease-out, box-shadow 0.12s ease-out, border-color 0.12s ease-out;

    &:hover { transform: translateY(-2px); border-color: var(--border); box-shadow: 0 10px 28px oklch(0.2 0 0 / 0.10); }
  }
  .portal-card-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 20px; }
  .portal-card-name { font-size: 17px; font-weight: 700; letter-spacing: -0.02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: auto; }
  /* The brand chip only appears in a relay's portal, so it must not eat the name's room. */
  .portal-card-head .client-chip { margin-right: -8px; }
  .portal-card .status-pill { flex-shrink: 0; }
  .portal-card-grid { display: grid; grid-template-columns: 1.5fr 1fr 1.25fr 0.8fr; gap: 24px; align-items: start; }
  .portal-card .stat-label { font-size: 10px; font-weight: 700; letter-spacing: 0.09em; margin-bottom: 8px; }
  .portal-card .stat-value { font-size: 14px; font-weight: 700; color: var(--ink); margin-top: 0; }
  .portal-focus { font-size: 13.5px; font-weight: 500; line-height: 1.5; color: var(--ink); }
  .portal-kpi-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
  .portal-kpi { font-size: 20px; font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; color: var(--ink); }
  .portal-spark { display: block; margin-top: 8px; }
  .portal-spark .spark { width: 100%; height: 26px; display: block; }
  .portal-last { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

  /* Reusable delta pill + direction colouring. One `dir-*` class on the parent
     tints the pill and (via currentColor) the sparkline end-dot. */
  .delta-pill { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; }
  .dir-good .delta-pill { color: var(--ok-strong); background: var(--ok-tint); }
  .dir-bad  .delta-pill { color: var(--err-strong); background: var(--err-tint); }
  .dir-flat .delta-pill { color: var(--muted); background: var(--hairline); }
  .portal-spark.dir-good { color: var(--ok-strong); }
  .portal-spark.dir-bad  { color: var(--err-strong); }
  .portal-spark.dir-flat { color: var(--dim); }

  /* ── Campaign show page ──────────────────────────── */
  .campaign-show { overflow-y: auto; container-type: inline-size; background: var(--page); }
  .campaign-show-head {
    display: flex; align-items: center; justify-content: space-between; gap: 20px;
    padding: 18px 30px; border-bottom: 1px solid var(--border2); background: var(--card);
  }
  .campaign-show-title { display: flex; align-items: center; gap: 12px; min-width: 0; }
  .campaign-show-title h1 { font-size: 18px; font-weight: 700; margin: 0; letter-spacing: -0.025em; }
  .campaign-back {
    display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
    padding: 7px 13px 7px 10px; border-radius: 999px; border: 1px solid var(--border);
    background: var(--card); color: var(--muted); font-size: 12.5px; font-weight: 600;
  }
  .campaign-back:hover { border-color: var(--label); background: var(--page); color: var(--soft); }
  .campaign-show-head .btn-queued {
    background: #FDF8EE; border-color: #EAD9B4; color: #8A6A3D; border-radius: 999px;
  }

  /* Cards float on the warm page with real gaps (no divided container). */
  .campaign-show-grid { display: grid; grid-template-columns: 1.7fr 1fr; gap: 20px; padding: 24px 30px; align-items: start; }
  .campaign-show-main, .campaign-show-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

  /* Softer, rounder buttons — scoped so the rest of the app is untouched */
  .campaign-show .btn { border-radius: 999px; padding: 9px 18px; }
  .campaign-show .btn-sm { padding: 6px 13px; }
  .campaign-show .btn-primary { box-shadow: 0 4px 14px oklch(0.49 0.184 270 / 0.24); }
  .campaign-show .btn-outline { border-radius: 999px; border-color: var(--border); color: var(--soft); }

  /* Now-working-on focus strip — a tinted card in the main column */
  .focus-strip {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    padding: 14px 18px; background: #EEF2FE; border: 1px solid #DCE4FB; border-radius: var(--r-card);
  }
  .focus-strip-label {
    display: flex; align-items: center; gap: 7px; flex-shrink: 0;
    font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: #3D52C8;
  }
  .focus-dot { position: relative; width: 7px; height: 7px; border-radius: 50%; background: #3D52C8; }
  /* A gentle "live" pulse so the current focus catches the eye. */
  .focus-dot::after {
    content: ""; position: absolute; inset: 0; border-radius: 50%; background: #3D52C8;
    animation: focusPulse 2.2s ease-out infinite;
  }
  @keyframes focusPulse {
    0%   { transform: scale(1); opacity: 0.5; }
    70%  { opacity: 0; }
    100% { transform: scale(3.4); opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) { .focus-dot::after { animation: none; } }
  .focus-strip-value { flex: 1; min-width: 180px; display: flex; align-items: center; gap: 8px; }
  .focus-strip-form { display: none; flex: 1; margin: 0; }
  .is-editing .focus-strip-form { display: flex; align-items: center; gap: 8px; }
  .is-editing .focus-strip-text, .is-editing .focus-strip-pencil { display: none; }
  .focus-strip-text {
    font-size: 19px; font-weight: 700; color: var(--accent-ink); line-height: 1.3;
    background: none; border: none; padding: 0; text-align: left; font-family: inherit; letter-spacing: -0.02em;
  }
  button.focus-strip-text { flex: 1; cursor: text; }
  button.focus-strip-text:hover { color: var(--accent); }
  .focus-strip-pencil {
    flex-shrink: 0; display: flex; background: none; border: none; padding: 2px; cursor: pointer;
    color: var(--accent); opacity: 0.55;
  }
  .focus-strip-pencil:hover { opacity: 1; }
  .focus-strip-input {
    flex: 1; min-width: 0; padding: 7px 11px; border: 1px solid var(--accent); border-radius: var(--r-md);
    font-size: 19px; font-weight: 700; color: var(--accent-ink); background: var(--card); outline: none;
    font-family: inherit; letter-spacing: -0.02em;
  }

  /* Details card — base, unchanged (shared with the creative-set overview card) */
  .details-card { background: var(--card); border: 1px solid var(--border2); border-radius: 10px; overflow: hidden; margin: 0; }
  .details-head { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid #E8E3DC; }
  .details-head .section-label { flex: 1; }
  .details-editing-note { display: none; flex: 1; font-size: 10.5px; font-weight: 600; color: var(--accent); }
  .is-editing .details-editing-note { display: block; }
  .is-editing .details-head .section-label { display: none; }
  .details-edit-btn { display: inline-flex; align-items: center; gap: 5px; }
  .is-editing .details-edit-btn { display: none; }

  /* Softer card — scoped to the campaign page only */
  .campaign-show .details-card { border-radius: var(--r-card); box-shadow: var(--shadow-sm); }
  .details-row { display: grid; grid-template-columns: 120px 1fr; gap: 12px; align-items: start; padding: 13px 16px; }
  .details-row + .details-row { border-top: 1px solid #E8E3DC; }
  .details-label { font-size: 9px; font-weight: 600; color: var(--label); letter-spacing: 0.08em; text-transform: uppercase; padding-top: 3px; }
  .details-value { font-size: 13.5px; font-weight: 700; min-width: 0; }
  .details-value .status-pill { font-size: 13px; }
  .stat-note { font-size: 9px; color: var(--label); margin-top: 6px; font-weight: 600; }
  .details-value .budget-bar { margin-top: 8px; }

  .details-edit { display: none; }
  .is-editing .details-static { display: none; }
  .is-editing .details-edit { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .details-select {
    appearance: none; padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px;
    font-size: 12.5px; font-weight: 600; color: var(--ink); background: var(--card); outline: none; font-family: inherit; cursor: pointer;
  }
  .details-select:focus { border-color: var(--accent); }
  .details-edit input[type="date"] {
    padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px;
    font-size: 12px; color: var(--ink); background: var(--card); outline: none; font-family: inherit;
  }
  .details-edit input[type="date"]:focus { border-color: var(--accent); }

  /* Campaign details edit mode — full-width rounded fields on the inset bg (scoped to
     .campaign-show; the base .details-edit is already flex-wrap, so a full-width child
     wraps to its own line and the two date inputs share a row). */
  .campaign-show :is(.details-select, .details-input, .budget-input, .budget-period) {
    width: 100%; padding: 8px 10px; border-radius: var(--r-md); background: var(--inset); font-size: 12px;
  }
  .campaign-show .details-edit input[type="date"] {
    flex: 1; min-width: 0; padding: 8px 10px; border-radius: var(--r-md); background: var(--inset); font-size: 12px;
  }

  .details-foot { display: none; justify-content: flex-end; gap: 8px; padding: 12px 16px; border-top: 1px solid #E8E3DC; background: var(--inset); }
  .is-editing .details-foot { display: flex; }
  .code-input { text-transform: uppercase; }
  /* Live chip preview beside the code field, so you see the mark you're editing. */
  .code-row { display: flex; align-items: center; gap: 10px; }
  .code-row .code-input { flex: 1; min-width: 0; }
  .field-note { font-size: 11px; color: var(--label); line-height: 1.5; margin: 2px 0 0; }

  /* Name field + read-only client code (both edit-only rows in the details card) */
  .details-input {
    padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px; width: 100%;
    font-size: 12.5px; font-weight: 600; color: var(--ink); background: var(--card); outline: none; font-family: inherit;
  }
  .details-input:focus { border-color: var(--accent); }
  .details-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.04em; color: var(--soft); }
  .details-row--edit-only { display: none; }
  .is-editing .details-row--edit-only { display: grid; }
  .details-note { display: block; font-size: 11px; color: var(--label); margin-top: 5px; max-width: 42ch; }
  .lib-home-select { width: 100%; padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--inset); font-family: inherit; font-size: 13px; color: var(--ink); }
  .lib-home-note { font-size: 11px; color: var(--label); margin: 6px 0 0; }

  /* Archived pill (reuses .status-pill via --sc) + banner */
  .archived-banner {
    display: flex; align-items: center; gap: 12px; justify-content: space-between;
    margin: 12px 0 0; padding: 11px 16px; border: 1px solid #E4D9C4; border-radius: 10px;
    background: #FBF6EC; color: #6E5A38; font-size: 12.5px; font-weight: 600;
  }

  /* Danger zone (own disclosure card, shown regardless of the details edit mode) */
  .btn-delete { background: #C0392B; color: #FDF3F1; }
  .btn-delete:disabled { background: #E7C9C4; color: #F7ECEA; cursor: not-allowed; }
  /* Shown only while the Campaign Details card is being edited (sibling of the form). */
  .danger-zone { margin-top: 16px; border-color: #E9C9C4; overflow: visible; }
  /* Hiding it until you're editing is the CAMPAIGN page's rule, not the danger zone's
     nature — so it hangs off that page's editing card rather than off the block itself.
     Elsewhere (the client's Settings tab) the zone simply shows. */
  .details-card ~ .danger-zone { display: none; }
  .details-card.is-editing ~ .danger-zone { display: block; }
  .danger-head { padding: 12px 16px; display: flex; align-items: baseline; gap: 8px; }
  .danger-head .section-label { color: #B3402F; }
  .danger-hint { font-size: 11px; color: var(--muted); font-weight: 500; }
  .danger-item { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 13px 16px; border-top: 1px solid #F0DAD5; }
  .danger-item-text { min-width: 0; }
  .danger-item-title { font-size: 12.5px; font-weight: 700; color: var(--ink); }
  .danger-item-desc { font-size: 11.5px; color: var(--muted); font-weight: 500; margin-top: 2px; line-height: 1.4; }
  .danger-item .btn { flex-shrink: 0; }
  .danger-delete .confirm-box .person-input {
    width: 100%; margin-bottom: 10px; border: 1px solid var(--border);
    border-radius: 6px; padding: 7px 9px; background: var(--inset);
  }

  .coming-soon-panel {
    border: 1.5px dashed #D8D0C4; border-radius: 10px; min-height: 220px; padding: 34px 24px;
    background: repeating-linear-gradient(135deg, #FAF8F4, #FAF8F4 11px, #F3EFE8 11px, #F3EFE8 22px);
    display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 12px;
  }
  .coming-soon-icon { width: 40px; height: 40px; border-radius: 10px; background: var(--card); border: 1px solid var(--border2); display: flex; align-items: center; justify-content: center; }
  .coming-soon-title { font-size: 14px; font-weight: 700; }
  .coming-soon-badge {
    display: inline-block; font-size: 9.5px; font-weight: 700; color: var(--soft); background: #EDEAE3;
    border: 1px solid var(--border); padding: 2px 9px; border-radius: 20px; letter-spacing: 0.06em; text-transform: uppercase; margin-left: 6px;
  }
  .coming-soon-text { margin: 0; max-width: 340px; font-size: 12px; color: var(--muted); line-height: 1.6; }

  /* Timeline panel (wraps the composer + history in the main column). NOT
     `.timeline-card` — that class is the internal-note callout body (below). */
  .timeline-panel {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); padding: 16px;
  }
  .timeline-panel > .section-label { display: block; margin-bottom: 12px; }
  .timeline { display: flex; flex-direction: column; max-height: 440px; overflow-y: auto; }
  .timeline-item { display: flex; gap: 10px; position: relative; }
  .timeline-icon {
    width: 14px; height: 16px; flex-shrink: 0; align-self: flex-start; margin-top: 2px; z-index: 1;
    display: flex; align-items: center; justify-content: center;
  }
  .timeline-icon svg { display: block; }
  .timeline-dot { width: 8px; height: 8px; border-radius: 50%; }
  .timeline-item:not(:last-child)::before {
    content: ""; position: absolute; left: 6.5px; top: 20px; bottom: 0; width: 1px; background: var(--border);
  }
  .timeline-body { padding-bottom: 18px; flex: 1; min-width: 0; }
  .timeline-date { font-size: 10.5px; color: var(--dim); margin-bottom: 3px; }
  .timeline-text { font-size: 12.5px; line-height: 1.5; }

  /* Timeline agency controls (edit / re-send / delete) */
  .timeline-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
  .timeline-actions { display: flex; align-items: center; gap: 2px; opacity: 0; transition: opacity 0.12s ease; }
  .timeline-item:hover .timeline-actions, .is-editing .timeline-actions { opacity: 1; }
  .timeline-action-form { display: inline; margin: 0; }
  .timeline-action {
    font-size: 10px; font-weight: 600; color: var(--muted); background: none; border: none;
    padding: 2px 5px; border-radius: 4px; cursor: pointer; font-family: inherit;

    &:hover { background: var(--hairline); color: var(--ink); }
  }
  .timeline-action--danger:hover { background: color-mix(in srgb, #C2542E 12%, transparent); color: #C2542E; }
  .timeline-edit-form { display: none; flex-direction: column; gap: 6px; margin: 6px 0 0; }
  .is-editing .timeline-edit-form { display: flex; }
  .is-editing .timeline-text { display: none; }
  .timeline-edit-input {
    width: 100%; padding: 6px 9px; border: 1px solid var(--accent); border-radius: 6px;
    font-size: 12.5px; color: var(--ink); background: var(--inset); outline: none; font-family: inherit; resize: vertical;
  }
  .timeline-edit-row { display: flex; align-items: center; gap: 6px; }

  .quick-log { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; }
  .timeline-panel > .request-change { margin-bottom: 16px; }
  .quick-log-input {
    padding: 9px 12px; border: 1px solid var(--border); border-radius: 7px; font-size: 12px;
    color: var(--ink); background: var(--card); outline: none; font-family: inherit; width: 100%;

    &:focus { border-color: var(--accent); }
  }
  .quick-log .btn { width: 100%; }
  .request-change > summary { list-style: none; width: 100%; text-align: center; }
  .request-change > summary::-webkit-details-marker { display: none; }
  .request-change[open] > summary { display: none; }
  .request-change-form { display: flex; flex-direction: column; gap: 6px; margin: 0; }
  .btn-request { background: #C2542E; color: #FDF6F2; width: 100%; }

  /* Composer: For-client / Internal-note toggle. All visual state is CSS off the
     checked radio (:has); only the placeholder is JS (composer_controller). */
  .composer { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; }
  .composer-toggle { display: flex; gap: 4px; background: var(--sidebar); padding: 4px; border-radius: 999px; }
  .composer-seg {
    flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 7px 0; border-radius: 999px; font-size: 11px; font-weight: 600; color: var(--muted);
    cursor: pointer; user-select: none; transition: color 0.12s ease, background 0.12s ease;
  }
  .composer-seg svg { display: block; }
  .composer-radio { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
  .composer-seg--client:has(:checked) { background: #fff; color: var(--accent); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
  .composer-seg--internal:has(:checked) { background: #fff; color: #6E6A86; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
  .composer-field { border-radius: 9px; }
  .composer:has(.composer-seg--internal :checked) .composer-field {
    background: #F5F3F8; border: 1px dashed #CFC9D6; padding: 9px;
  }
  .composer-submit {
    width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    background: var(--accent); color: var(--on-accent);
  }
  .composer:has(.composer-seg--internal :checked) .composer-submit { background: #6E6A86; color: #fff; }
  .composer-submit svg { display: block; }
  .composer-label-client, .composer-label-internal { display: inline-flex; align-items: center; gap: 5px; }
  .composer-label-internal { display: none; }
  .composer:has(.composer-seg--internal :checked) .composer-label-client { display: none; }
  .composer:has(.composer-seg--internal :checked) .composer-label-internal { display: inline-flex; }

  /* Internal timeline entry: slate padlock rail, INTERNAL pill, carded body. */
  .timeline-item--internal:not(:last-child)::before { background: #D8D2E0; }
  .internal-pill {
    display: inline-block; margin-left: 6px; vertical-align: middle;
    font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
    color: #6E6A86; background: #EFEDF3; border: 1px solid #DDD8E5; border-radius: 4px; padding: 1px 5px;
  }
  .timeline-card {
    background: #F5F3F8; border-left: 2px solid #6E6A86; border-radius: 0 6px 6px 0;
    padding: 7px 10px; color: #4A4640; margin-top: 2px;
  }

  /* Rounded square, not a circle: the chip reads as a brand mark rather than a person,
     which matters now that people and clients sit side by side on the same cards. Still
     the single seam for a future uploaded client photo — hence overflow: hidden. */
  .client-chip {
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 30px; height: 30px; border-radius: 9px; overflow: hidden;
    font-size: 9.5px; font-weight: 800; letter-spacing: 0.02em; line-height: 1;
    color: #F8F7F4; background: var(--cc, var(--accent));
  }
  .client-chip--lg { width: 34px; height: 34px; border-radius: 10px; font-size: 10.5px; }


  /* Inline-editable campaign fields (agency): type, budget, schedule */
  .kind-edit { margin: 0; }
  .kind-select {
    appearance: none; border: 1px solid var(--border); cursor: pointer; font-family: inherit;

    &:focus { outline: none; border-color: var(--accent); }
  }
  .budget-input {
    width: 72px; padding: 4px 6px; border: 1px solid var(--border); border-radius: 6px;
    font-size: 13px; font-weight: 700; color: var(--ink); background: var(--card); outline: none; font-family: inherit;

    &:focus { border-color: var(--accent); }
  }
  .budget-period, .schedule-edit input {
    appearance: none; padding: 4px 6px; border: 1px solid var(--border); border-radius: 6px;
    font-size: 11px; color: var(--soft); background: var(--card); outline: none; font-family: inherit; cursor: pointer;

    &:focus { border-color: var(--accent); }
  }
  .schedule-edit { display: flex; align-items: center; gap: 6px; margin: 0; }
  .schedule-edit input { cursor: text; }

  .name-row { display: flex; gap: 8px; }
  .name-row input { flex: 1; min-width: 0; }

  /* Status chip + dropdown menu. Campaign statuses (10 hues) are a coloured dot +
     coloured text driven by the inline --sc — no alpha-tinted background. Approval
     statuses (4) opt into a filled semantic tint via a --green/--amber/--danger/
     --neutral modifier below (bg + ink + dot from tokens, --sc ignored). */
  .status-pill {
    display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
    padding: 5px 11px; border-radius: 999px; white-space: nowrap;
    color: color-mix(in srgb, var(--sc) 82%, #241A12);
  }
  .status-pill--green   { background: var(--ok-tint);    color: var(--ok-strong);  border: 1px solid color-mix(in srgb, var(--ok-strong) 18%, transparent); }
  .status-pill--amber   { background: var(--amber-tint); color: var(--amber-ink);  border: 1px solid color-mix(in srgb, var(--amber-ink) 18%, transparent); }
  .status-pill--danger  { background: var(--err-tint);   color: var(--err-strong); border: 1px solid color-mix(in srgb, var(--err-strong) 18%, transparent); }
  .status-pill--neutral { background: var(--sidebar);    color: var(--soft);       border: 1px solid var(--border2); }
  .status-pill--green   .status-dot { background: #2F9E6E; }
  .status-pill--amber   .status-dot { background: var(--badge-amber); }
  .status-pill--danger  .status-dot { background: #C8452F; }
  .status-pill--neutral .status-dot { background: var(--dim); }
  .status-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--sc); flex-shrink: 0; }
  .status-caret { opacity: 0.6; }

  .status-menu { position: relative; display: inline-block; }
  .status-menu > summary { list-style: none; cursor: pointer; }
  .status-menu > summary::-webkit-details-marker { display: none; }

  .status-options {
    position: absolute; top: 100%; left: 0; margin-top: 4px; z-index: 30;
    background: var(--card); border: 1px solid var(--border2); border-radius: 8px;
    box-shadow: 0 10px 28px oklch(0.2 0 0 / 0.14); min-width: 190px; padding: 4px;
    display: flex; flex-direction: column; margin-bottom: 0;
  }
  .status-option {
    display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 10px;
    border: none; background: transparent; border-radius: 6px; cursor: pointer; text-align: left;
    font-size: 12px; font-weight: 500; color: var(--ink);

    &:hover { background: var(--hairline); }
  }
  .status-option-label { flex: 1; }
  .status-check { color: var(--accent); font-weight: 700; }

  /* The same control laid flat: every state visible at once, current one lit. Each stop is
     a real submit button in one form, so it works exactly like the menu's options do. */
  .status-strip {
    display: flex; gap: 3px; background: var(--inset); border: 1px solid var(--border2);
    border-radius: 999px; padding: 3px; margin: 0;
  }
  .status-stop {
    display: inline-flex; align-items: center; gap: 6px; padding: 6px 13px;
    border: none; background: transparent; border-radius: 999px; cursor: pointer;
    font-family: inherit; font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap;

    &:hover { color: var(--ink); }
    /* Dots stay off until the stop is current — four coloured dots in a row is a legend,
       not a control. */
    .status-dot { background: currentColor; opacity: 0.35; }
    &.is-current {
      background: var(--card); color: var(--ink); box-shadow: 0 1px 3px oklch(0.2 0 0 / 0.1);
      .status-dot { background: var(--sc); opacity: 1; }
    }
  }

  .heatmap {
    display: grid; grid-template-rows: repeat(7, 3px); grid-auto-flow: column;
    grid-template-columns: repeat(12, 3px); gap: 1px;
  }
  .heatmap-cell {
    width: 3px; height: 3px;
    background: #EFEBE4;

    &.heat-1 { background: #B9C6F2; }
    &.heat-2 { background: var(--accent); }
  }

  /* Slideover */
  .slideover-backdrop {
    position: fixed; inset: 0; background: oklch(0.2 0 0 / 0.32);
    display: flex; justify-content: flex-end; z-index: 40; animation: fadeIn 0.15s ease;
  }
  .slideover {
    width: 380px; max-width: 100%; height: 100%; background: var(--card);
    box-shadow: -8px 0 24px oklch(0.2 0 0 / 0.12);
    display: flex; flex-direction: column; animation: slideIn 0.22s ease;
  }
  .slideover--wide { width: 420px; }
  .slideover > form { flex: 1; display: flex; flex-direction: column; min-height: 0; }
  .slideover-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 20px; border-bottom: 1px solid var(--border2); }
  .slideover-head h2 { font-size: 14.5px; margin: 0; letter-spacing: -0.02em; }
  .slideover-close { background: none; border: none; font-size: 18px; color: var(--dim); cursor: pointer; line-height: 1; padding: 2px; }
  .slideover-body { flex: 1; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 16px; }
  .slideover-foot { padding: 16px 20px; border-top: 1px solid var(--border2); }
  .slideover-foot .btn { width: 100%; padding: 11px; }
  .slideover-body .field-stack { display: flex; flex-direction: column; gap: 6px; }
  .slideover-body .field-stack > label, .slideover-body > label { font-size: 11.5px; font-weight: 500; color: var(--soft); }
  .slideover-body input[type="text"], .slideover-body input[type="number"], .slideover-body input[type="date"],
  .slideover-body input[type="email"], .slideover-body select, .slideover-body textarea {
    padding: 9px 11px; border: 1.5px solid var(--border); border-radius: var(--r-md);
    font-size: 13px; color: var(--ink); background: var(--inset); outline: none; width: 100%;

    &:focus { border-color: var(--accent); }
  }
  .form-errors { background: oklch(0.95 0.03 25); border: 1px solid oklch(0.85 0.08 25); border-radius: var(--r); padding: 10px 14px; font-size: 12px; color: var(--err); }
  .form-errors ul { margin: 0; padding-left: 18px; }

  .toggle-group { display: flex; gap: 6px; flex-wrap: wrap; }
  .toggle-pill {
    position: relative; font-size: 12px; font-weight: 600; padding: 8px 14px; border-radius: var(--r-md);
    border: 1.5px solid var(--border); color: var(--soft); cursor: pointer; background: var(--card);

    & input { position: absolute; opacity: 0; pointer-events: none; }
    &:has(input:checked) { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  }

  .budget-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .budget-row input[type="number"] { flex: 1; min-width: 90px; }
  .currency-select { flex: 0 0 auto; width: auto; }
  .date-row { display: flex; gap: 10px; }
  .date-row input { flex: 1; }
  .label-optional { color: var(--dim); font-weight: 500; text-transform: none; letter-spacing: 0; }
  .field-help { font-size: 11px; color: var(--dim); line-height: 1.5; margin: 8px 0 0; }
  .field-help strong { color: var(--soft); font-weight: 600; }

  .register-toggle {
    display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--soft);
    background: var(--inset); border: 1px solid var(--border2); border-radius: var(--r-md); padding: 11px 12px; cursor: pointer;
  }

  /* Toast — flash notice, bottom-center, self-dismissing */
  .toast {
    position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
    /* ⚠ It fades with `forwards` but never leaves the DOM, and the alert variant never fades
       at all — so without this it goes on swallowing clicks over the foot of every page. */
    pointer-events: none;
    background: var(--ink); color: var(--on-accent); padding: 10px 18px; border-radius: var(--r-md);
    font-size: 12.5px; font-weight: 500; z-index: 50; box-shadow: 0 8px 24px oklch(0.2 0 0 / 0.2);
    white-space: nowrap; animation: toast 3.2s ease forwards;

    /* A refusal is longer than an FYI and worth reading twice — it wraps, and it stays put
       rather than sliding away mid-sentence. */
    &.toast--alert {
      background: oklch(0.45 0.17 25); white-space: normal; max-width: min(480px, calc(100vw - 32px));
      text-align: center; line-height: 1.5; animation: none;
    }
  }

  .slideover--wide { width: 420px; }

  /* ── Clients page ────────────────────────────────── */
  .tab-chips { display: flex; gap: 6px; margin-top: 6px; }
  .tab-chip {
    font-size: 11px; font-weight: 600; color: var(--soft); background: var(--sidebar);
    padding: 4px 11px; border-radius: 20px; text-decoration: none;

    &.is-active { background: var(--accent); color: var(--on-accent); }
  }

  /* Shared people atoms — used by the Client Detail team card + add-staff form. */
  .person-avatar {
    width: 26px; height: 26px; border-radius: 50%; background: var(--sidebar); color: var(--soft);
    flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 9.5px; font-weight: 700;
    overflow: hidden;

    &--primary { background: var(--accent); color: var(--on-accent); }
  }
  .person-input {
    border: none; background: transparent; font-size: 13px; font-weight: 500; color: var(--ink);
    outline: none; padding: 3px 4px; font-family: inherit; border-radius: 4px; min-width: 40px;

    &:focus { background: var(--inset); }
  }
  /* Shape encodes access: a circle for someone who can sign in, a rounded square for an
     address we only ever write to. */
  .person-avatar--square { border-radius: 9px; }
  .primary-badge { font-size: 8.5px; font-weight: 700; color: var(--accent); background: var(--accent-soft); padding: 2px 6px; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.04em; flex-shrink: 0; }

  /* One form, two homes: the People card's + Add and a row's Edit. Both stack, because
     both expand inside .cd-card, which is overflow:hidden. */
  .person-form { display: flex; flex-direction: column; align-items: stretch; gap: 6px; margin: 0; }
  .person-form .person-input { border: 1px solid var(--border); border-radius: 6px; padding: 7px 9px; background: var(--inset); }
  .person-form-label { font-size: 9.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--label); margin-top: 4px; }
  .person-form-check { display: flex; align-items: flex-start; gap: 7px; font-size: 11px; color: var(--soft); line-height: 1.4; }
  .person-form-note { font-size: 10.5px; color: var(--label); line-height: 1.45; margin: -2px 0 2px; }

  /* Inline confirm disclosure (archive / remove) */
  .inline-confirm { position: relative; }
  .inline-confirm > summary { list-style: none; cursor: pointer; }
  .inline-confirm > summary::-webkit-details-marker { display: none; }
  .confirm-box {
    position: absolute; top: 100%; right: 0; margin-top: 6px; z-index: 30; width: 260px;
    background: #FDF3EE; border: 1px solid #F0DCCF; border-radius: var(--r-md); padding: 14px;
    box-shadow: 0 10px 28px oklch(0.2 0 0 / 0.14);
  }
  .confirm-box p { margin: 0 0 12px; font-size: 12px; color: var(--soft); line-height: 1.5; }
  .confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }
  .confirm-actions form { margin: 0; }

  /* ── Clients roster table ────────────────────────── */
  .clients-table {
    max-width: 880px; margin: 16px 0 0; background: var(--card); border: 1px solid var(--border2);
    border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden;
  }
  .clients-row {
    display: grid; grid-template-columns: minmax(0,1.7fr) 104px 80px 132px 16px; gap: 16px;
    align-items: center; padding: 14px 20px; border-top: 1px solid var(--hairline);
    text-decoration: none; color: inherit; transition: background 0.12s ease;
  }
  .clients-row:hover { background: var(--inset); }
  /* A sub-client, tucked under the brand that relays for it. */
  .clients-row--nested { background: var(--sidebar); }
  .clients-row--nested .clients-name { font-size: 13px; font-weight: 600; }
  .clients-elbow { width: 12px; height: 12px; margin-left: 8px; border-left: 1.5px solid var(--border); border-bottom: 1.5px solid var(--border); border-bottom-left-radius: 4px; flex-shrink: 0; align-self: flex-start; margin-top: -2px; }
  .clients-foot { padding: 12px 20px; font-size: 11px; color: var(--label); }
  .clients-row--head {
    padding: 13px 20px; background: var(--page); border-top: none; border-bottom: 1px solid var(--border2);
    font-size: 10px; font-weight: 700; color: var(--label); letter-spacing: 0.09em; text-transform: uppercase;
  }
  .clients-cell-client { display: flex; align-items: center; gap: 12px; min-width: 0; }
  .clients-name { font-size: 14px; font-weight: 700; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .queued-capsule { font-size: 9.5px; font-weight: 700; color: var(--amber-ink); background: var(--amber-tint); padding: 2px 7px; border-radius: 999px; text-transform: uppercase; letter-spacing: 0.03em; flex-shrink: 0; }
  .clients-count { font-size: 13px; font-weight: 600; color: var(--soft); }
  .clients-activity { font-size: 12px; color: var(--dim); }
  .clients-chev { color: #C0B8AE; }

  /* ── Client Detail page ──────────────────────────── */
  .client-detail { overflow-y: auto; container-type: inline-size; background: var(--page); }
  /* Identity + tabs: the page's fixed chrome. Only .cd-panel changes between tabs. */
  .cd-head { border-bottom: 1px solid var(--border2); background: var(--card); }
  .cd-head-row {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    max-width: 1320px; margin: 0 auto; padding: 16px 32px 0;
  }
  .cd-title { display: flex; align-items: center; gap: 11px; min-width: 0; }
  .cd-title h1 { font-size: 19px; font-weight: 800; margin: 0; letter-spacing: -0.025em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cd-divider { width: 1px; height: 22px; background: var(--border2); flex-shrink: 0; }
  .cd-head-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
  .cd-head-actions .btn-primary { border-radius: 999px; padding: 10px 18px; font-size: 12.5px; box-shadow: 0 4px 14px oklch(0.49 0.184 270 / 0.26); }
  /* The relay's code, faded, in front of the brand's own — same size, no name. This tile
     is what says "sub-client"; there is deliberately no badge saying it as well. */
  .cd-parent-tile {
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 34px; height: 34px; border-radius: 10px; text-decoration: none;
    background: var(--sidebar); color: var(--label);
    font-size: 10.5px; font-weight: 800; letter-spacing: 0.02em; line-height: 1;
  }
  .cd-parent-tile:hover { color: var(--accent); }
  .cd-crumb-sep { font-size: 17px; font-weight: 700; color: var(--border); margin: 0 -3px; }

  .cd-tabs { display: flex; gap: 2px; max-width: 1320px; margin: 14px auto -1px; padding: 0 32px; }
  .cd-tab {
    padding: 10px 14px 12px; font-size: 13px; font-weight: 600; color: var(--soft);
    text-decoration: none; border-bottom: 2px solid transparent; white-space: nowrap;
  }
  .cd-tab:hover { color: var(--ink); }
  .cd-tab.is-active { font-weight: 700; color: var(--ink); border-bottom-color: var(--accent); }

  .cd-panel { display: flex; flex-direction: column; gap: 20px; max-width: 1320px; margin: 0 auto; width: 100%; padding: 24px 32px 48px; }
  /* Reading-width surfaces: a full-bleed 1320px form is unreadable. */
  .cd-panel .links-card, .cd-panel .cd-settings, .cd-panel .danger-zone { max-width: 720px; }
  .client-detail .archived-banner { max-width: 1320px; margin: 16px auto 0; }

  .settings-row { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 14px; align-items: center; padding: 10px 16px; border-top: 1px solid var(--hairline); }
  .settings-key { font-size: 11.5px; font-weight: 600; color: var(--soft); }
  .settings-value { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 600; color: var(--ink); min-width: 0; flex-wrap: wrap; }
  .settings-note { font-size: 11px; font-weight: 400; color: var(--label); }
  .settings-input { border: 1px solid var(--border); border-radius: 7px; padding: 7px 10px; background: var(--inset); font-family: inherit; font-size: 13px; color: var(--ink); min-width: 0; width: 100%; }
  .settings-value .settings-input { width: auto; flex: 1; }
  .settings-input--num { max-width: 120px; flex: 0 0 auto; }
  .cd-card-head--sub { padding-top: 18px; border-top: 1px solid var(--hairline); }

  /* Three states that exclude each other, each carrying the sentence that says what it
     does. Radio rows rather than pills — this is a choice, not a set of toggles. */
  .status-choice { display: grid; grid-template-columns: 16px 90px minmax(0, 1fr); gap: 12px; align-items: center; padding: 11px 16px; border-top: 1px solid var(--hairline); cursor: pointer; }
  .status-choice.is-chosen { background: var(--inset); }
  .status-radio { position: absolute; opacity: 0; width: 0; height: 0; }
  .status-choice-dot { width: 15px; height: 15px; border-radius: 50%; border: 1.5px solid var(--border); }
  .status-choice:has(.status-radio:checked) .status-choice-dot { border: 4.5px solid var(--sc); }
  .status-choice-name { font-size: 12.5px; font-weight: 600; color: var(--soft); }
  .status-choice:has(.status-radio:checked) .status-choice-name { font-weight: 700; color: var(--sc); }
  .status-choice-hint { font-size: 11.5px; color: var(--muted); line-height: 1.45; }

  /* The bar reveals itself once the flag inside it goes dirty — no second controller and
     no state to keep in step, just :has over draft_form's own class. */
  /* The flag lives inside the bar, so the bar can ask about itself — no card name in the
     selector, and every form that wants a confirm bar gets one for free. */
  .settings-bar { display: none; align-items: center; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--hairline); background: var(--sidebar); }
  .settings-bar:has(.settings-dirty.is-dirty) { display: flex; }
  .settings-dirty { margin-right: auto; font-size: 11.5px; font-weight: 600; color: var(--warn-ink, var(--soft)); }

  /* Link-a-client drawer: two modes, switched by radios and :has — no controller. */
  .link-modes { display: flex; gap: 3px; margin: 14px 20px 0; padding: 4px; background: var(--sidebar); border-radius: 999px; }
  .link-mode { flex: 1; text-align: center; padding: 7px 12px; border-radius: 999px; font-size: 12.5px; font-weight: 600; color: var(--soft); cursor: pointer; }
  .link-mode-radio { position: absolute; opacity: 0; width: 0; height: 0; }
  .link-mode:has(.link-mode-radio:checked) { background: var(--card); color: var(--accent-ink); box-shadow: var(--shadow-sm); }
  .link-modal-card:has(.link-mode-radio[value=attach]:checked) .link-pane--create,
  .link-modal-card:has(.link-mode-radio[value=create]:checked) .link-pane--attach { display: none; }
  .link-search {
    width: 100%; padding: 8px 11px; font: inherit; font-size: 12.5px;
    border: 1px solid var(--border2); border-radius: var(--r-md); background: var(--card);

    &:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
  }
  /* The confirm reads the radios directly, so "nothing is selected" is stated once. A
     disabled attribute would be a second copy of it to keep in step — including after
     list-filter clears a hidden pick. */
  .link-pane--attach:not(:has(.attach-radio:checked)) [type=submit] {
    opacity: 0.45; pointer-events: none;
  }
  .attach-list { display: flex; flex-direction: column; gap: 4px; max-height: 320px; overflow-y: auto; }
  .attach-option { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--r-md); cursor: pointer; }
  .attach-option:hover { background: var(--inset); }
  .attach-option:has(.attach-radio:checked) { background: var(--accent-soft); }
  .attach-radio { width: 13px; height: 13px; accent-color: var(--accent); flex-shrink: 0; }
  .attach-name { font-size: 13px; font-weight: 600; margin-right: auto; }
  .attach-meta { font-size: 11px; color: var(--soft); }

  /* Dense campaign row: spent/budget left, percent right, over the bar they describe. */
  .cbr-budget-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .cbr-money { font-size: 12.5px; font-weight: 700; color: var(--ink); }
  .cbr-pct { font-size: 11px; font-weight: 600; color: var(--soft); }

  /* Library TAB: a reading list — icon, name, badges, first line of the body.
     ⚠ Scoped to .lib-list on purpose. The Library *page* has its own `.lib-row`, a
     five-column grid with pin/share toggles, defined further down and therefore winning
     on order. Two different rows genuinely want the same word; the scope keeps them apart
     without renaming a class the other page already uses. */
  .lib-list .cd-card-head { padding: 14px 16px; }
  .lib-list .search-pill { max-width: 300px; }
  .lib-list .lib-row { display: flex; align-items: flex-start; gap: 11px; padding: 11px 16px; border-top: 1px solid var(--hairline); text-decoration: none; color: inherit; }
  .lib-list .lib-row:hover { background: var(--inset); }
  .lib-row-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .lib-row-top { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
  .lib-row-name { font-size: 13px; font-weight: 700; }
  .lib-row-preview { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lib-badge { font-size: 8.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; padding: 2px 6px; border-radius: 4px; background: var(--sidebar); color: var(--soft); white-space: nowrap; }
  .lib-badge--pinned { background: var(--accent-soft); color: var(--accent-ink); }
  .lib-list-foot { display: flex; justify-content: flex-end; padding: 10px 16px; border-top: 1px solid var(--hairline); background: var(--inset); }

  /* Scope of work: a fixed table of service lines, four exclusive owners each. Every client
     gets the same editable card — nothing here is ever disabled or rolled up. */
  .scope-engagement { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 13px 16px; border-top: 1px solid var(--hairline); }
  .scope-switch { display: inline-flex; align-items: center; gap: 8px; }
  .scope-switch-label { font-size: 11.5px; font-weight: 600; color: var(--label); }
  .scope-switch:has(input:checked) .scope-switch-label { color: var(--ink); }
  .scope-segments { display: inline-flex; gap: 3px; padding: 3px; background: var(--sidebar); border-radius: 999px; }
  .scope-seg { padding: 5px 12px; border-radius: 999px; font-size: 11.5px; font-weight: 600; color: var(--soft); cursor: pointer; }
  .scope-seg-radio { position: absolute; opacity: 0; width: 0; height: 0; }
  .scope-seg:has(.scope-seg-radio:checked) { background: var(--card); color: var(--ink); box-shadow: var(--shadow-sm); }

  .scope-row { display: grid; grid-template-columns: minmax(0, 1.1fr) 300px minmax(0, 1fr); gap: 20px; align-items: center; padding: 10px 16px; border-top: 1px solid var(--hairline); }
  .scope-row--head { font-size: 9px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--label); }
  .scope-name { display: flex; align-items: center; gap: 9px; font-size: 12.5px; font-weight: 600; min-width: 0; }
  /* ⚠ Row state reads the CHECKED RADIO, not a class from the server, so the dot and the
     excluded styling change on click like the pills do rather than lagging until save. The
     owner colours live here for the same reason — nothing in Ruby holds them. Browser-verified
     only: no request test can assert a style a selector derives. */
  .scope-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border); flex-shrink: 0; }
  .scope-row:has(.scope-pill--us       .scope-pill-radio:checked) .scope-dot { background: #3D52C8; }
  .scope-row:has(.scope-pill--client   .scope-pill-radio:checked) .scope-dot { background: #7A7268; }
  .scope-row:has(.scope-pill--external .scope-pill-radio:checked) .scope-dot { background: #B8862E; }
  /* "Nobody" is an agreement, so the row stays legible while reading as settled. */
  .scope-row:has(.scope-pill--not-included .scope-pill-radio:checked) {
    background: var(--inset);
    .scope-dot { background: #C0B8AE; }
    .scope-name { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--border); }
  }
  .scope-owners { display: inline-flex; gap: 4px; }
  .scope-pill { padding: 4px 10px; border-radius: 999px; border: 1px solid var(--hairline); background: var(--card); font-size: 10.5px; font-weight: 600; color: var(--label); cursor: pointer; white-space: nowrap; }
  .scope-pill-radio { position: absolute; opacity: 0; width: 0; height: 0; }
  .scope-pill:has(.scope-pill-radio:checked) { border-color: var(--border); color: var(--ink); }
  .scope-pill--us:has(.scope-pill-radio:checked) { border-color: var(--accent-border); background: var(--accent-soft); color: var(--accent-ink); }
  .scope-pill--external:has(.scope-pill-radio:checked) { border-color: oklch(0.8712 0.0722 82); background: oklch(0.9532 0.0338 86); color: #8A6220; }
  .scope-volume { border: none; background: transparent; font-family: inherit; font-size: 12px; color: var(--ink); padding: 4px 6px; border-radius: 5px; width: 100%; min-width: 0; }
  .scope-volume:focus { background: var(--inset); outline: none; }

  .danger-confirm { position: relative; }
  .danger-form { display: flex; flex-direction: column; gap: 8px; }
  .danger-form .person-input { border: 1px solid var(--border); border-radius: 6px; padding: 7px 9px; background: var(--inset); width: 100%; }
  .client-detail .btn { border-radius: 999px; }
  .client-detail .btn-sm { padding: 6px 13px; }

  /* Campaigns & creative band */
  /* .cd-panel centres and pads its children, so the band no longer carries its own. */
  .campaigns-band { width: 100%; }
  .campaigns-band-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 12px; }
  .campaigns-band-summary { font-size: 11.5px; color: var(--muted); }
  .campaigns-band-list { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden; }
  .campaigns-band-row {
    display: grid; grid-template-columns: minmax(0,1.6fr) 172px minmax(0,1.5fr) 14px; gap: 20px;
    align-items: center; padding: 12px 18px; border-top: 1px solid var(--hairline);
    text-decoration: none; color: inherit; transition: background 0.12s ease;
  }
  .campaigns-band-row:first-child { border-top: none; }
  .campaigns-band-row:hover { background: var(--inset); }
  .cbr-name { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .cbr-name > .status-dot { flex-shrink: 0; }
  .cbr-title { font-size: 13.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .cbr-name .status-pill { flex-shrink: 0; font-size: 10.5px; padding: 3px 9px; }
  .cbr-budget-top { font-size: 11.5px; font-weight: 700; white-space: nowrap; }
  .cbr-budget .budget-bar { margin-top: 5px; }
  .cbr-budget .stat-note { font-size: 10px; margin-top: 4px; }
  .cbr-assets { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; min-width: 0; }
  .cbr-assets-label { font-size: 9px; font-weight: 700; color: var(--label); text-transform: uppercase; letter-spacing: 0.06em; padding-right: 12px; border-right: 1px solid var(--border2); }
  .cbr-assets-seg { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; color: var(--soft); }
  .cbr-assets-seg.is-muted { font-weight: 600; color: var(--muted); }
  .cbr-assets-seg .creative-band-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--sc, var(--dim)); flex-shrink: 0; }
  .cbr-chev { color: #C0B8AE; }

  /* Right-rail cards (Library module + team) */
  .cd-card { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden; }
  .cd-card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px 8px; }
  .cd-mini-btn {
    border: 1px solid var(--border); background: var(--card); color: var(--soft); border-radius: 7px;
    padding: 3px 10px; font-size: 10.5px; font-weight: 600; cursor: pointer; font-family: inherit;
    list-style: none; line-height: 1.5;
  }
  .cd-mini-btn::-webkit-details-marker { display: none; }
  .cd-mini-btn:hover { border-color: var(--label); }
  .cd-mini-btn--edit { border-color: var(--accent-border); color: var(--accent-ink); }
  .cd-mini-btn--add { border: 1px dashed var(--border); color: var(--soft); }
  .cd-mini-btn--add:hover { border-color: var(--accent); color: var(--accent); }
  /* Copy-button label swap, driven by clipboard_controller's .is-copied. Unscoped so any
     button can wear it — each then says for itself what "copied" looks like (.cd-mini-btn
     greens just the word; .share-copy greens the whole button). */
  .cd-mini-done { display: none; }
  .is-copied .cd-mini-label { display: none; }
  .is-copied .cd-mini-done { display: inline; }
  .cd-mini-btn .cd-mini-done { color: var(--ok-strong); }

  /* Links & IDs — external addresses (Asana/Canva/Drive/inboxes) on the client rail */
  .links-card { padding-bottom: 6px; }
  .links-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 16px; border-top: 1px solid var(--hairline); }
  .links-row-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .links-key { font-size: 9.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--label); }
  .links-name { font-size: 12.5px; font-weight: 600; color: var(--accent-ink); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .links-name:hover { text-decoration: underline; }
  .links-inboxes { font-family: var(--mono); font-size: 11px; color: var(--ink); overflow-wrap: anywhere; }
  .links-id { flex-shrink: 0; font-family: var(--mono); font-size: 10.5px; color: var(--soft); background: var(--sidebar); border: 1px solid var(--border); border-radius: 6px; padding: 3px 8px; }
  /* Inherited from the parent client: present, usable, but not this client's to edit. */
  .links-row.is-inherited .links-name { color: var(--soft); font-weight: 500; }
  .links-row.is-inherited .links-id { color: var(--label); }
  .links-via { font-size: 10px; font-style: italic; color: var(--label); }
  .links-empty-lead { font-size: 12px; color: var(--soft); line-height: 1.5; margin: 2px 16px 10px; }
  .links-ghost-row { display: flex; align-items: center; gap: 8px; margin: 0 16px 8px; padding: 9px 12px; border: 1px dashed var(--border); border-radius: var(--r-md); font-size: 11.5px; color: var(--label); }
  .links-ghost-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--border); }
  .links-add-btn { display: block; margin: 4px 16px 12px; text-align: center; }
  .ref-label-input { margin-top: 4px; }
  .slideover-body .ref-input, .slideover-body .ref-label-input { font-family: var(--mono); font-size: 12px; }

  /* People card. Both disclosures on it work the same way: the trigger is lifted out of
     flow to a corner, and the form it opens expands in place. */
  .cd-team { position: relative; }
  .cd-add > summary { position: absolute; top: 14px; right: 16px; }
  .cd-add .person-form { margin: 0 16px 12px; }
  /* ⚠ The People card holds popovers (grant access, edit) that open past its last row,
     and .cd-card clips. Third time this has bitten: the Add form in the tab-shell phase
     was the same. Anything on this card that opens downward needs the card to let it. */
  .cd-team { overflow: visible; }
  .cd-team .cd-person-row:last-child { border-radius: 0 0 var(--r-card) var(--r-card); }

  .cd-card-headings { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .cd-card-sub { font-size: 11px; color: var(--soft); }
  .cd-card-hint { font-size: 10.5px; color: var(--label); }

  /* Who a person is to the client. A label only — mail routing is the notify pill. */
  .role-tag {
    flex-shrink: 0; padding: 2px 6px; border-radius: 5px; font-size: 8.5px; font-weight: 800;
    letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.5;
  }
  .role-tag--relay    { background: oklch(0.9312 0.0448 84.2); color: oklch(0.4412 0.0812 62.4); }
  .role-tag--client   { background: var(--sidebar); color: var(--soft); }
  .role-tag--internal { background: var(--accent-soft); color: var(--accent-ink); }

  /* People table. Grid on the row itself so the head and every row line up by
     construction rather than by two lists of widths kept in step by hand. */
  .cd-person-row {
    position: relative; display: grid; gap: 18px; align-items: center;
    grid-template-columns: minmax(0, 1fr) 84px 140px 140px 110px 74px;
    padding: 12px 16px; border-top: 1px solid var(--hairline);
  }
  .cd-person-head { font-size: 9px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--label); padding: 10px 16px; }
  /* ⚠ Load-bearing: without it the rows below paint over an open access popover. The
     brief flags this as a real bug found in review, and it is not a cosmetic rule. */
  .cd-person:has(details[open]) { position: relative; z-index: 60; }
  .cd-person-cell { display: flex; align-items: center; gap: 10px; min-width: 0; }
  .cd-person.is-emailed { background: var(--inset); }
  .cd-person-who { min-width: 0; }
  .cd-person-line { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .cd-person-name { font-size: 13.5px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cd-person-title { font-size: 11px; color: var(--soft); }
  .cd-person-email { font-family: var(--mono); font-size: 11px; color: var(--label); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cd-person-via { font-family: var(--sans, inherit); font-style: italic; color: var(--label); text-decoration: none; margin-left: 6px; }
  .cd-person-via:hover { color: var(--accent); }
  .cd-person-dash { color: var(--border); }
  .cd-person-actions { justify-content: flex-end; }
  /* An inherited person is shown, not managed — their controls live on the parent. */
  .cd-person.is-inherited .perm-pill, .cd-person.is-inherited .switch { opacity: 0.7; cursor: default; }


  .access-grant > summary { list-style: none; cursor: pointer; }
  .access-grant > summary::-webkit-details-marker { display: none; }
  .access-grant .confirm-box { position: absolute; z-index: 50; width: 250px; margin-top: 6px; }
  .confirm-note { font-size: 11px; color: var(--muted); line-height: 1.45; margin: 4px 0 0; }
  .perm-pill.is-static { cursor: default; }
  .cd-person-editor { position: absolute; z-index: 50; right: 16px; margin-top: 6px; width: 280px; padding: 12px; background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-md); box-shadow: 0 10px 28px oklch(0.2 0 0 / 0.14); }
  .cd-person-remove-btn { margin-top: 8px; background: none; border: none; padding: 0; font-family: inherit; font-size: 11px; font-weight: 600; color: var(--err); cursor: pointer; }

  .cd-perm-pills { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; padding-left: 36px; }
  .perm-pill {
    display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 999px;
    font-size: 10.5px; font-weight: 600; cursor: pointer; border: 1px solid var(--border); background: var(--card); color: var(--dim);
  }
  .perm-pill-check { position: absolute; opacity: 0; width: 0; height: 0; }
  .perm-pill:has(.perm-pill-check:checked) { border-color: var(--accent-border); background: var(--accent-soft); color: var(--accent-ink); }
  .perm-pill--reports:has(.perm-pill-check:checked) { border-color: var(--border); background: var(--sidebar); color: var(--soft); }
  /* Access is not a permission — it decides whether the others can apply at all — so it
     reads as solid rather than tinted when on.
     ⚠ This was `--access:has(:checked)` until the access cell became a button_to (there is
     no checkbox in a button, which is exactly why an enabled toggle rendered identical to a
     disabled one). One state, one block, worn by whatever renders it. */
  .perm-pill--on { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
  /* Any pill carrying both labels swaps them on check — it was scoped to --scope when
     that was the only such pill, and access is now the second. Pills without the two
     spans are unaffected. */
  .perm-pill .perm-on { display: none; }
  .perm-pill:has(.perm-pill-check:checked) .perm-on { display: inline; }
  .perm-pill:has(.perm-pill-check:checked) .perm-off { display: none; }

  /* Sub-clients: the brands this client relays for. */
  .subclient-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto 14px; gap: 10px; align-items: center; padding: 11px 16px; border-top: 1px solid var(--hairline); text-decoration: none; color: inherit; }
  .subclient-row:hover { background: var(--inset); }
  .subclient-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .subclient-count, .subclient-contact { font-size: 11px; color: var(--soft); white-space: nowrap; }
  .subclient-empty { font-size: 12px; color: var(--soft); line-height: 1.5; margin: 2px 16px 14px; }

  /* Client detail header: the relay's name sits above a sub-client's own. */

  .cd-archive-zone { display: flex; justify-content: flex-end; padding: 4px 2px; }
  .cd-archive-btn { color: var(--muted); }

  .timeline-source { font-size: 9px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; margin-left: 6px; }

  @container (max-width: 900px) {
    .cd-head-row { flex-wrap: wrap; padding: 14px 20px 0; }
    .cd-tabs { padding: 0 20px; overflow-x: auto; }
    .cd-panel { padding: 20px; }
    .campaigns-band { padding: 0; }
    .campaigns-band-row { grid-template-columns: 1fr; gap: 8px; }
    .cbr-assets-label { border-right: none; padding-right: 0; }

    /* ⚠ A @container, not a @media query: the People table is constrained by the CARD it
       sits in, not by the window. The sidebar takes ~240px, so a 900px window leaves this
       page ~660px — under the 638px the six fixed columns and their gaps need before the
       1fr person column gets anything at all. Sized to the viewport it looked fine on a
       phone and collapsed the names to zero width on a small laptop.
       Below here the columns stop being columns: the person keeps one line and the
       controls wrap under them. The head goes too — a header names a column, and there
       are none left to name. */
    .cd-person-head { display: none; }
    .cd-person-row { grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
    .cd-person-row > .cd-person-cell:nth-child(n + 2):not(.cd-person-actions) { grid-column: 1; }
    .cd-person-actions { grid-row: 1; grid-column: 2; align-self: start; }
    /* A bare switch says nothing once "Approve creative" is no longer written above it. The
       pills still read as themselves, so only what needs a label carries one. */
    .cd-person-row > form[data-label]::before {
      content: attr(data-label); font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
      text-transform: uppercase; color: var(--label);
    }
  }

  /* ── Settings / Account ──────────────────────────── */
  .settings-body { flex: 1; overflow-y: auto; max-width: 604px; padding: 24px 24px 72px; display: flex; flex-direction: column; gap: 8px; }
  .settings-body .section-label { display: block; margin: 32px 0 12px; }
  .settings-card { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden; }
  .settings-card--split { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 24px; }

  .settings-identity { display: flex; align-items: center; gap: 16px; padding: 22px 24px; border-bottom: 1px solid var(--hairline); }
  .settings-avatar-form { margin: 0; }
  .settings-avatar { position: relative; display: block; cursor: pointer; border-radius: 50%; }
  .settings-avatar-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
  .settings-avatar-hint {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    border-radius: 50%; background: rgba(28,26,24,0.55); color: #fff; font-size: 9.5px; font-weight: 600;
    opacity: 0; transition: opacity 0.12s;
  }
  .settings-avatar:hover .settings-avatar-hint, .settings-avatar:focus-within .settings-avatar-hint { opacity: 1; }
  .settings-name { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
  .settings-identity-sub { font-size: 11.5px; color: var(--dim); margin-top: 3px; }
  .settings-photo-link { border: none; background: transparent; padding: 0; margin-top: 3px; font-size: 11.5px; font-weight: 600; color: var(--accent); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
  .settings-inline-form { margin: 0; flex: 1; }
  .settings-input {
    width: 100%; border: none; background: transparent; font-size: 13.5px; color: var(--ink);
    font-family: inherit; padding: 4px 6px; margin: -4px -6px; border-radius: 5px; outline: none;

    &:focus { background: var(--inset); }
  }

  .settings-card-row { display: flex; align-items: center; gap: 16px; padding: 14px 24px; border-bottom: 1px solid var(--hairline); }
  .settings-card-row--last { border-bottom: none; }
  .settings-key { width: 110px; flex-shrink: 0; font-size: 12px; font-weight: 600; color: var(--soft); }
  .settings-value { font-size: 13.5px; color: var(--ink); }
  .settings-value--muted { color: var(--muted); }

  .settings-item-title { font-size: 13px; font-weight: 600; }
  .settings-item-desc { font-size: 11.5px; color: var(--dim); margin-top: 3px; line-height: 1.4; }
  .settings-row { display: flex; align-items: center; gap: 8px; }

  .avatar-lg { width: 52px; height: 52px; font-size: 17px; background: var(--accent); color: var(--on-accent); }
  .soon-tag { font-size: 10px; font-weight: 600; color: var(--label); text-transform: uppercase; letter-spacing: 0.05em; }
  .api-key-mask { font-family: var(--mono); font-size: 11px; color: var(--soft); background: var(--inset); border: 1px solid var(--border2); padding: 6px 10px; border-radius: var(--r); }
  .is-soon { opacity: 0.55; cursor: not-allowed; }
  .settings-card--split form { margin: 0; }

  /* Toggle switch */
  .switch { position: relative; display: inline-block; cursor: pointer; flex-shrink: 0; }
  .switch input { position: absolute; opacity: 0; width: 0; height: 0; }
  .switch-track { display: block; width: 34px; height: 20px; border-radius: 10px; background: oklch(0.86 0.012 84.6); transition: background 0.15s ease; }
  .switch-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px oklch(0.2 0 0 / 0.25); transition: left 0.15s ease; }
  .switch:has(input:checked) .switch-track { background: var(--accent); }
  .switch:has(input:checked) .switch-track::after { left: 16px; }

  /* ── Integrations ────────────────────────────────── */
  .tool-sub { font-size: 11.5px; color: var(--dim); margin-top: 2px; }
  /* Full-width scroll region (scrollbar sits at the window edge, not mid-screen); the
     content itself is capped, so the cards read at a comfortable width. */
  .integrations-body { flex: 1; overflow-y: auto; padding: 24px 24px 72px; display: flex; flex-direction: column; gap: 14px; }
  .integrations-grid, .integration-request { max-width: 604px; }
  .integrations-grid { display: grid; grid-template-columns: 1fr; gap: 14px; align-items: start; }

  /* Revoke confirm renders inline within the panel (not the shared absolute popover,
     which would overflow off the narrow card's left edge). */
  .integration-panel .confirm-box { position: static; width: auto; right: auto; margin-top: 10px; box-shadow: none; }

  /* Fathom uses the connector card wholesale — same <details>, same summary, same panel —
     because it is the same kind of thing: a secret you set from this page. Its field is
     .conn-code like the ones above it, so there is nothing bespoke to style here beyond
     letting the Save button sit beside the input. */
  .conn-field .btn { flex-shrink: 0; }

  .integration-request { display: flex; align-items: center; gap: 12px; margin-top: 14px; padding: 16px 18px; border: 1px dashed var(--border); border-radius: var(--r-card); }
  .integration-request-tile { flex-shrink: 0; width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; font-size: 20px; color: var(--muted); background: var(--inset); }
  .integration-request-text { flex: 1; min-width: 0; }
  .integration-request-link { flex-shrink: 0; font-size: 12px; font-weight: 600; color: var(--accent); text-decoration: none; }
  .integration-request-link:hover { text-decoration: underline; }

  .integration-card { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden; }
  .integration-summary { display: flex; align-items: center; gap: 12px; padding: 16px; cursor: pointer; list-style: none; }
  .integration-summary::-webkit-details-marker { display: none; }
  .integration-summary:hover { background: var(--inset); }
  .integration-tile { flex-shrink: 0; width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center; font-size: 18px; background: #F6EAE3; color: #C15F3C; }
  .integration-headtext { flex: 1; min-width: 0; }
  .integration-toggle { flex-shrink: 0; }
  .integration-toggle .toggle-close { display: none; }
  .integration-card[open] > .integration-summary .toggle-open { display: none; }
  .integration-card[open] > .integration-summary .toggle-close { display: inline; }
  .conn-label-hint { font-weight: 400; color: var(--muted); font-style: italic; }
  .conn-badge { display: inline-block; margin-left: 6px; vertical-align: middle; font-size: 9.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--ok-strong); background: var(--ok-tint); border-radius: 999px; padding: 2px 7px; }

  .integration-panel { border-top: 1px solid var(--border2); background: var(--inset); padding: 16px; display: flex; flex-direction: column; gap: 12px; }
  .conn-nudge { font-size: 11.5px; line-height: 1.45; color: var(--ok-strong); background: var(--ok-tint); border: 1px solid oklch(0.86 0.05 155 / 0.6); border-radius: 10px; padding: 10px 12px; }
  .conn-ro { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; font-size: 10.5px; font-weight: 700; color: var(--accent); background: oklch(0.96 0.02 270); border: 1px solid var(--accent-border); border-radius: 999px; padding: 4px 10px; }

  .conn-field-group { display: flex; flex-direction: column; gap: 5px; }
  .conn-label { font-size: 11px; font-weight: 600; color: var(--soft); }
  .conn-field { display: flex; align-items: center; gap: 8px; }
  .conn-field .cd-mini-btn { flex-shrink: 0; }
  .conn-code { flex: 1; min-width: 0; font-family: var(--mono); font-size: 12px; color: var(--ink); background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 9px 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .conn-code--masked { color: var(--muted); }
  .conn-hint { font-size: 11px; color: var(--muted); }

  .conn-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .conn-actions form { margin: 0; }

  .conn-steps { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--soft); line-height: 1.45; }
  .conn-steps strong { color: var(--ink); font-weight: 600; }
  .conn-advanced { border-top: 1px solid var(--border2); margin-top: 4px; padding-top: 10px; }
  .conn-advanced > summary { list-style: none; cursor: pointer; font-size: 11.5px; font-weight: 600; color: var(--muted); }
  .conn-advanced > summary::-webkit-details-marker { display: none; }
  .conn-advanced > summary::before { content: "▸ "; }
  .conn-advanced[open] > summary::before { content: "▾ "; }
  .conn-advanced-body { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
  .conn-advanced-body .btn { align-self: flex-start; }
  .conn-advanced-body form { margin: 0; }
  .conn-code code, .conn-hint code { font-family: var(--mono); }

  /* Claude OAuth consent screen (doorkeeper) */
  .consent-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--sidebar); }
  .consent-card { width: 100%; max-width: 440px; background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); box-shadow: var(--shadow-sm); padding: 28px; }
  .consent-brand { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 14px; color: var(--ink); margin-bottom: 20px; }
  .consent-title { font-size: 19px; font-weight: 800; letter-spacing: -0.02em; margin: 0 0 8px; color: var(--ink); }
  .consent-sub { font-size: 13px; color: var(--soft); line-height: 1.5; margin: 0 0 16px; }
  .consent-scopes { list-style: none; margin: 0 0 16px; padding: 14px 16px; background: var(--inset); border: 1px solid var(--border2); border-radius: 12px; display: flex; flex-direction: column; gap: 8px; font-size: 12.5px; color: var(--soft); }
  .consent-scopes li { display: flex; align-items: baseline; gap: 8px; }
  .consent-ok { color: var(--ok-strong); font-weight: 700; }
  .consent-no { color: var(--muted); font-weight: 700; }
  .consent-redirect { font-size: 11.5px; color: var(--muted); margin: 0 0 20px; }
  .consent-redirect code, .consent-signed code { font-family: var(--mono); }
  .consent-actions { display: flex; gap: 10px; }
  .consent-actions form { margin: 0; flex: 1; }
  .consent-actions .btn { width: 100%; justify-content: center; }
  .consent-signed { font-size: 11px; color: var(--label); margin: 16px 0 0; text-align: center; }

  /* ── Login ───────────────────────────────────────── */
  .auth { min-height: 100vh; display: flex; flex-direction: column; align-items: center; padding: 24px; background: var(--sidebar); }
  .auth-inner { width: 100%; max-width: 360px; margin: auto 0; }
  .auth-brand { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 36px; font-size: 18px; font-weight: 700; letter-spacing: -0.03em; }
  .auth-card { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-xl); padding: 36px 32px 32px; }
  .auth-card h1 { font-size: 20px; font-weight: 700; letter-spacing: -0.03em; margin: 0 0 4px; }
  .auth-sub { font-size: 13px; color: var(--dim); margin: 0 0 28px; }
  .auth-fields { display: flex; flex-direction: column; gap: 16px; }
  .auth-field label { font-size: 12px; font-weight: 500; color: var(--soft); display: block; margin-bottom: 6px; }
  .auth-field .field-head { display: flex; align-items: center; justify-content: space-between; }
  .auth-field .field-head a { font-size: 11.5px; font-weight: 500; }
  .auth-field input {
    width: 100%; padding: 10px 13px; border: 1.5px solid var(--border); border-radius: var(--r-md);
    font-size: 13.5px; color: var(--ink); background: var(--inset); outline: none;

    &:focus { border-color: var(--accent); }
  }
  .auth-submit { width: 100%; padding: 11px; margin-top: 4px; font-size: 13.5px; }
  .auth-submit:disabled { background: #E4DFD7; color: var(--label); cursor: not-allowed; }
  .auth-footer { text-align: center; font-size: 11.5px; color: var(--label); margin-top: 20px; }

  .auth-back {
    display: inline-flex; align-items: center; gap: 5px; background: none; border: none; padding: 0;
    margin: 0 0 18px; font-size: 12px; font-weight: 500; color: var(--soft); cursor: pointer; font-family: inherit;
  }
  .auth-link { background: none; border: none; padding: 0; font-size: 12px; font-weight: 600; color: var(--accent); cursor: pointer; font-family: inherit; display: inline; }

  /* Access gate — where a share link lands someone who can't open it yet. The .auth
     shell, re-spaced: a lock, a strip naming the work behind it, and one way in. Scoped
     under .gate so every rule outspecifies the login page's without cancelling it. */
  .auth-inner.gate { max-width: 400px; }
  .gate .auth-brand { margin-bottom: 18px; font-size: 17px; }
  .gate .auth-card {
    padding: 32px 30px 28px; text-align: center;
    display: flex; flex-direction: column; align-items: center; gap: 12px;
  }
  .gate .auth-card h1 { font-size: 19px; margin: 0; }
  .gate .auth-sub { margin: 0; color: var(--muted); line-height: 1.6; }
  .gate-lock {
    width: 42px; height: 42px; border-radius: 50%; flex-shrink: 0;
    background: var(--icon-tile); color: var(--muted);
    display: flex; align-items: center; justify-content: center;
  }
  .gate-strip {
    width: 100%; margin-top: 4px; padding: 12px 14px; text-align: left;
    background: var(--page); border: 1px solid var(--border2); border-radius: var(--r-lg);
    display: flex; align-items: center; gap: 11px;
  }
  .gate-code {
    width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
    background: var(--accent-soft); color: var(--accent-ink); font-size: 11px; font-weight: 700;
    display: flex; align-items: center; justify-content: center;
  }
  .gate-strip-text { min-width: 0; }
  .gate-set { font-size: 13px; font-weight: 700; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .gate-meta { font-size: 11.5px; color: var(--dim); margin-top: 1px; }
  .gate-cta { display: block; margin-top: 6px; border-radius: var(--r-md); text-decoration: none; text-align: center; }
  .gate-note { font-size: 11.5px; color: var(--dim); margin-top: 2px; }
  .gate-signout { display: inline; }

  .digit-boxes { display: flex; gap: 8px; margin-bottom: 6px; }
  .digit-box {
    flex: 1; min-width: 0; height: 54px; text-align: center; font-family: var(--mono); font-size: 22px; font-weight: 700;
    color: var(--ink); border: 1.5px solid var(--border); border-radius: 10px; background: var(--inset); outline: none; padding: 0;

    &:focus { border-color: var(--accent); }
    &:not(:placeholder-shown) { border-color: var(--accent); }
  }

  /* Creator credit pill (login only) */
  .credit-pill {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 6px 14px 6px 6px;
    background: #FFFFFF; border: 1px solid #E8E3DC; border-radius: 999px;
    font-size: 12px; font-weight: 500; color: #4A4640; letter-spacing: -0.01em;
    text-decoration: none; white-space: nowrap;
  }
  .credit-pill-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }

  /* ── Creative Approvals ──────────────────────────── */
  /* Board reuses the campaigns dashboard table (.campaigns-table / .campaign-row
     / .client-chip / .status-pill). Only the client-group divider + the mobile
     card reflow are page-specific — scoped under .creative-approvals. */
  .creative-approvals .campaigns-table { min-width: 680px; }
  .creative-approvals .cs-group-head { display: none; }          /* desktop: chip repeats per row instead */
  .creative-approvals .cs-group-start > td { border-top: 1px solid var(--border2); }
  .creative-approvals td[data-cell="Type"] { color: var(--soft); }
  .creative-approvals .cs-row-meta { display: none; }          /* mobile-only; a real column on desktop */

  @media (max-width: 720px) {
    .creative-approvals .campaigns-table-wrap { overflow: visible; }
    .creative-approvals .campaigns-table { min-width: 0; }
    .creative-approvals .campaigns-table thead { display: none; }
    .creative-approvals .campaigns-table,
    .creative-approvals .campaigns-table tbody,
    .creative-approvals .campaigns-table tr,
    .creative-approvals .campaigns-table td { display: block; }

    /* sticky client (or campaign) group header */
    .creative-approvals .cs-group-head { display: block; position: sticky; top: 0; z-index: 2;
      background: var(--sidebar); border-top: 1px solid var(--border2); border-bottom: 1px solid var(--hairline); }
    .creative-approvals .cs-group-head td { display: flex; align-items: center; gap: 10px; padding: 8px 16px; border: none; }
    .creative-approvals .cs-group-name { font-size: 13px; font-weight: 700; letter-spacing: -0.01em; }
    .creative-approvals .cs-group-count { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--soft); }

    /* each set → a card: title + status on line 1, campaign · type · assets on line 2, updated on line 3 */
    .creative-approvals .campaigns-table tbody tr.campaign-row,
    .creative-approvals .campaigns-table tbody tr.campaign-row--alt {
      display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; row-gap: 3px;
      padding: 13px 16px; border-top: none; border-bottom: 1px solid var(--hairline); background: var(--card);
    }
    .creative-approvals .cs-group-start > td { border-top: none; }
    .creative-approvals tr.campaign-row .cs-client-cell { display: none; }   /* client lives in the header */
    .creative-approvals tr.campaign-row .campaign-name { order: 1; flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 700; white-space: normal; padding: 0; }
    .creative-approvals tr.campaign-row td:has(> .status-pill) { order: 2; flex: 0 0 auto; padding: 0; }
    .creative-approvals tr.campaign-row td[data-cell] { display: none; }        /* columns collapse into the meta line */
    .creative-approvals tr.campaign-row .cs-row-meta { display: block; order: 3; flex-basis: 100%; padding: 0; font-size: 12px; color: var(--soft); }
    /* The ⋯ rides the right edge of the card's last line, same as it rides the right edge of
       the row on desktop. (This cell is display:block from the reflow above, so it says flex
       here rather than relying on the desktop rule, which loses on specificity.) */
    .creative-approvals tr.campaign-row .campaign-last-update {
      order: 4; flex-basis: 100%; padding: 2px 0 0;
      display: flex; align-items: center; justify-content: space-between;
    }
  }

  /* Creative-set page (agency management) */
  .creative-show { overflow-y: auto; }
  .creative-show-body { max-width: 620px; margin: 0 auto; padding: 24px; display: flex; flex-direction: column; gap: 16px; }
  .creative-advance { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
  .creative-advance-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
  .creative-advance-buttons form { margin: 0; }
  .creative-delete { color: #C2542E; align-self: flex-start; }
  .creative-delete:hover { background: color-mix(in srgb, #C2542E 10%, transparent); }

  /* Portal-card creative footer band */
  .creative-band {
    display: flex; align-items: center; flex-wrap: wrap; gap: 18px;
    margin: 18px -24px -20px; padding: 14px 24px;
    border-top: 1px solid var(--hairline); background: #FAF8F4; border-radius: 0 0 var(--r-card) var(--r-card);
  }
  .creative-band-label {
    display: inline-flex; align-items: center; gap: 7px;
    padding-right: 16px; border-right: 1px solid var(--border2);
    color: var(--label); font-size: 10px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  }
  .creative-band-label svg { color: var(--dim); }
  .creative-band-seg { display: inline-flex; align-items: center; gap: 7px; font-size: 11.5px; font-weight: 700; color: color-mix(in srgb, var(--sc) 84%, #241A12); }
  .creative-band-seg.is-muted { font-weight: 600; color: var(--muted); }
  .creative-band-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--sc); flex-shrink: 0; }

  /* Campaign-show "Creatives in production" card */
  .creatives-card { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden; }
  .creatives-card-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 10px; }
  .creatives-card-head .section-label { flex: 1; }
  .creatives-card-count { font-size: 11px; font-weight: 600; color: var(--soft); background: var(--page); border-radius: 999px; padding: 3px 10px; }
  .creatives-list { display: flex; flex-direction: column; gap: 2px; padding: 0 8px 8px; }
  .creatives-row { display: flex; align-items: center; gap: 12px; padding: 10px; border-radius: var(--r-tile); text-decoration: none; color: inherit; }
  a.creatives-row:hover { background: var(--page); }
  .creatives-tile {
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    width: 36px; height: 36px; border-radius: var(--r-tile); background: var(--accent-soft); color: var(--accent);
  }
  .creatives-tile-ok { background: color-mix(in srgb, var(--ok) 15%, transparent); color: var(--ok); }
  .creatives-row-main { flex: 1; min-width: 0; }
  .creatives-row-title { font-size: 12.5px; font-weight: 700; letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .creatives-row-meta { font-size: 11px; color: var(--dim); margin-top: 2px; }
  .creatives-row .status-pill { flex-shrink: 0; }
  .creatives-approved { flex: 1; font-size: 12px; font-weight: 600; color: var(--soft); }
  .creatives-viewall { font-size: 11.5px; font-weight: 600; color: var(--accent); flex-shrink: 0; }
}

@layer components {
  /* ── Mobile (single breakpoint) ──────────────────────
     The sidebar goes off-canvas behind a CSS-only checkbox toggle (#nav_toggle
     in the layout) — sibling selectors only, no :has(), no JS. Turbo re-renders
     <body> on every visit, so the menu closes itself after navigating. */
  .nav-toggle-input, .bottom-bar, .menu-sheet { display: none; }

  @media (max-width: 700px) {
    .app { flex-direction: column; height: 100dvh; }

    /* Bottom tab bar — a flex child pinned to the base of the column, so the
       .main above it simply shrinks (no fixed-overlap padding needed). */
    .bottom-bar {
      display: flex; justify-content: space-around; flex-shrink: 0; position: relative;
      background: var(--card); border-top: 1px solid var(--border2);
      padding: 9px 10px calc(10px + env(safe-area-inset-bottom));
    }
    .tab {
      display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1;
      text-decoration: none; color: var(--dim); background: none; border: none; cursor: pointer;
    }
    .tab-icon {
      position: relative; width: 54px; height: 32px; border-radius: 999px;
      display: flex; align-items: center; justify-content: center;
    }
    .tab-label { font-size: 10.5px; font-weight: 600; letter-spacing: -0.01em; }
    .tab.is-active { color: var(--accent); }
    .tab.is-active .tab-icon { background: var(--accent-soft); }
    .tab.is-active .tab-label { font-weight: 700; }

    /* The desktop rail is replaced by the bottom bar + Menu sheet on mobile. */
    .sidebar { display: none; }

    /* Queue FAB — floats over the bar's top edge (agency only). */
    .nav-fab {
      position: absolute; right: 22px; top: -30px; width: 56px; height: 56px;
      display: flex; align-items: center; justify-content: center;
      border-radius: 50%; background: var(--accent); color: #fff;
      box-shadow: 0 10px 24px oklch(0.49 0.184 270.5 / 0.42);
    }
    .count-badge--fab {
      position: absolute; top: -2px; right: -2px;
      min-width: 20px; height: 20px; padding: 0 5px; font-size: 10.5px; border: 2.5px solid var(--page);
    }

    /* Full-screen Menu sheet, toggled by the hamburger (#nav_toggle). */
    .nav-toggle-input:checked ~ .menu-sheet { display: flex; }
    .menu-sheet {
      position: fixed; inset: 0; z-index: 70; flex-direction: column;
      background: var(--page); animation: fadeIn 0.15s ease;
    }
    .menu-head { padding: 16px 20px 14px; background: var(--card); border-bottom: 1px solid var(--border2); }
    .menu-head-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
    .menu-title { font-size: 19px; font-weight: 800; letter-spacing: -0.02em; }
    .menu-close {
      width: 34px; height: 34px; border-radius: 50%; background: var(--sidebar); color: var(--soft);
      display: flex; align-items: center; justify-content: center; font-size: 20px; line-height: 1; cursor: pointer;
    }
    .menu-workspace {
      display: flex; align-items: center; gap: 12px; padding: 11px 13px;
      background: var(--page); border: 1px solid var(--border2); border-radius: var(--r-xl); color: inherit;
    }
    .menu-brand {
      width: 38px; height: 38px; border-radius: 11px; background: var(--accent-soft);
      display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    }
    .menu-org { font-size: 14px; font-weight: 700; }

    .menu-groups { flex: 1; overflow-y: auto; padding: 8px 12px 16px; display: flex; flex-direction: column; gap: 12px; }
    .menu-group-label { font-size: 9.5px; font-weight: 700; letter-spacing: 0.11em; text-transform: uppercase; color: var(--label); padding: 12px 12px 6px; }
    .menu-card { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card); overflow: hidden; box-shadow: var(--shadow-sm); }
    .menu-item {
      display: flex; align-items: center; gap: 13px; padding: 14px 15px;
      border-top: 1px solid var(--hairline); color: inherit; text-decoration: none;

      &:first-child { border-top: none; }
      &:hover { background: var(--inset); }
    }
    .menu-tile {
      width: 40px; height: 40px; border-radius: 11px; background: var(--icon-tile); color: #4A4640;
      display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    }
    .menu-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
    .menu-label { font-size: 14px; font-weight: 600; }
    .menu-sub { font-size: 11.5px; color: var(--dim); margin-top: 1px; }
    .menu-chevron { color: var(--chevron); flex-shrink: 0; }
    .menu-indicator { width: 126px; height: 5px; border-radius: 999px; background: oklch(0.22 0.005 68 / 0.85); margin: 8px auto 12px; }

    /* Two-column layouts stack; fixed desktop paddings shrink.
       (The campaign show page stacks via a @container query — see below.) */
    .portal-card-grid { grid-template-columns: 1fr; }
    .clipper { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) 320px; }
    .settings-body { padding: 24px 16px 48px; }
    /* Wrap the actions under the title on narrow screens. Deliberately NOT re-padding:
       the header must keep the 24px that .campaigns-body uses, or they misalign. */
    .tool-header { flex-wrap: wrap; gap: 10px; }
    .clients-list { padding: 0 16px; }

    /* Drawers go full-width (the campaigns table keeps horizontal scroll
       via .campaigns-body { overflow: auto }) */
    .slideover, .slideover--wide { width: 100%; }

    /* iOS Safari zooms into any focused text field below 16px — the !important
       is needed to beat the drawer's class-level 11–13px sizes here only. */
    input:not([type="checkbox"], [type="radio"]), select, textarea { font-size: 16px !important; }

    .toast { white-space: normal; max-width: calc(100vw - 32px); text-align: center; }
  }

  /* Campaign show stacks on its own content width (sidebar-agnostic), so it
     folds on a narrow laptop window too — not just at the mobile breakpoint. */
  @container (max-width: 760px) {
    .campaign-show-grid { grid-template-columns: 1fr; padding: 16px; gap: 14px; }
    .campaign-show-head { flex-wrap: wrap; gap: 10px; padding: 16px 18px; }
  }

  /* Styled confirmation dialog (see application.js — every data-turbo-confirm) */
  .confirm-dialog {
    border: none; border-radius: 14px; padding: 0; max-width: 380px; width: calc(100% - 40px);
    background: var(--card); color: var(--ink); box-shadow: 0 20px 50px oklch(0.2 0 0 / 0.25);
  }
  .confirm-dialog::backdrop { background: oklch(0.2 0 0 / 0.35); }
  .confirm-card { margin: 0; padding: 22px 24px; display: flex; flex-direction: column; gap: 8px; }
  .confirm-title { font-size: 15px; font-weight: 700; margin: 0; letter-spacing: -0.01em; }
  .confirm-message { font-size: 12.5px; color: var(--muted); line-height: 1.55; margin: 0 0 8px; }
  .confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }
}

/* ── Performance reporting ───────────────────────────── */
@layer components {
  .budget-bar:has(> span) { background: var(--hairline); }
  .budget-bar > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
  .budget-bar.is-over > span { background: var(--err); }

  .perf-card {
    display: block; background: var(--card); border: 1px solid var(--border2);
    border-radius: var(--r-card); box-shadow: var(--shadow-sm); padding: 20px 22px;
  }
  .perf-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }

  .perf-metrics { position: relative; }
  .perf-metrics > summary { list-style: none; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
  .perf-metrics > summary::-webkit-details-marker { display: none; }

  .perf-kpi { margin-top: 4px; }
  .perf-kpi-label { font-size: 10.5px; letter-spacing: 0.06em; color: var(--muted); font-weight: 600; }
  .perf-kpi-row { display: flex; align-items: center; gap: 12px; margin-top: 2px; }
  .perf-kpi-value { font-size: 40px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.05; color: var(--ink); }
  .perf-kpi-caption { font-size: 11.5px; color: var(--dim); margin-top: 4px; }
  .perf-delta {
    display: inline-flex; align-items: center; font-size: 11.5px; font-weight: 600;
    padding: 4px 10px; border-radius: 999px; background: var(--inset); color: var(--soft);
  }
  .perf-delta-good { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }
  .perf-delta-bad  { background: color-mix(in srgb, var(--err) 12%, transparent); color: var(--err); }

  .perf-stepper { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin: 10px 0 2px; }
  .perf-stepper-label { font-size: 12.5px; font-weight: 600; color: var(--ink); min-width: 96px; text-align: center; }
  .perf-step {
    display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 24px;
    border: 1px solid var(--border2); border-radius: var(--r-sm); color: var(--soft);
    text-decoration: none; font-size: 14px; line-height: 1;
  }
  .perf-step:hover { background: var(--inset); }
  .perf-step.is-off { opacity: 0.35; pointer-events: none; }

  .perf-chart-wrap { position: relative; margin: 8px 0 4px; }
  .perf-chart { display: block; width: 100%; height: 200px; }
  .perf-grid { stroke: var(--border2); stroke-width: 1; }
  .perf-guide {
    position: absolute; top: 8px; bottom: 8px; width: 1px; background: var(--accent-border);
    opacity: 0; transform: translateX(-0.5px); pointer-events: none; transition: opacity 0.1s;
  }
  .perf-tip {
    position: absolute; top: 0; transform: translateX(-50%); opacity: 0; pointer-events: none;
    background: var(--ink); color: #fff; border-radius: var(--r); padding: 8px 10px; font-size: 11px;
    white-space: nowrap; box-shadow: 0 6px 20px oklch(0.2 0 0 / 0.18); transition: opacity 0.1s; z-index: 2;
  }
  .perf-tip-date { font-weight: 700; margin-bottom: 4px; opacity: 0.85; }
  .perf-tip-row { display: flex; align-items: center; gap: 6px; }
  .perf-tip-row b { margin-left: auto; padding-left: 12px; }
  .perf-tip-dot { width: 7px; height: 7px; border-radius: 50%; }

  .perf-legend { display: flex; flex-wrap: wrap; gap: 16px; margin: 6px 0 14px; }
  .perf-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--soft); }
  .perf-legend-item b { color: var(--ink); }
  .perf-legend-dot { width: 8px; height: 8px; border-radius: 50%; }

  .perf-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); border-radius: var(--r-tile); overflow: hidden; }
  .perf-stat { padding: 10px 12px; background: var(--card); }
  .perf-stat-label { font-size: 9.5px; letter-spacing: 0.05em; color: var(--muted); font-weight: 600; }
  .perf-stat-value { font-size: 15px; font-weight: 700; color: var(--ink); margin-top: 3px; }

  .perf-adsets { margin-top: 12px; border: 1px solid var(--border2); border-radius: var(--r-tile); background: var(--inset); }
  .perf-adsets > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; font-size: 12.5px; }
  .perf-adsets > summary::-webkit-details-marker { display: none; }
  .perf-adsets-title { font-weight: 600; }
  .perf-adsets-hint { font-size: 11px; color: var(--dim); }
  .perf-adsets-list { margin: 0; padding: 0 4px; }
  .perf-adset { display: flex; align-items: center; gap: 11px; padding: 9px 8px; border-top: 1px solid var(--hairline); font-size: 12.5px; }
  .perf-adset-main { display: flex; flex-direction: column; min-width: 0; }
  .perf-adset-name { font-weight: 600; font-size: 11.5px; }
  .perf-adset-dates { color: var(--dim); font-size: 9.5px; margin-top: 1px; }
  /* Footer bar: helper line (nothing ticked) ⇄ Remove pill (ticked), Add-data always. */
  .perf-adsets-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; padding: 10px 12px; border-top: 1px solid var(--hairline); background: var(--inset); }
  .perf-adsets-hint-line { flex: 1; min-width: 120px; font-size: 10px; color: var(--dim); line-height: 1.5; }
  .perf-adsets-actions { display: flex; align-items: center; gap: 7px; flex-shrink: 0; }
  .perf-add-form { margin: 0; }
  .perf-add-btn {
    display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    background: var(--accent-soft); color: var(--accent-ink); border-radius: 999px; padding: 7px 14px;
    font-size: 11px; font-weight: 600;
  }
  .perf-add-btn:hover { background: var(--accent-nav); }
  .perf-remove { display: none; background: color-mix(in srgb, var(--err) 10%, transparent); color: var(--err); border: 1px solid color-mix(in srgb, var(--err) 25%, transparent); }
  .perf-adsets-body:has(.perf-adset-check:checked) .perf-adsets-hint-line { display: none; }
  .perf-adsets-body:has(.perf-adset-check:checked) .perf-remove { display: inline-flex; }

  .perf-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hairline); }
  .perf-foot-note { font-size: 11.5px; color: var(--dim); }
  .perf-foot-actions { display: flex; align-items: center; gap: 7px; }

  .perf-import { margin-top: 14px; }
  .perf-import-compact { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
  .perf-drop {
    display: flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer;
    border: 1px dashed var(--accent-border); border-radius: var(--r-tile); padding: 12px 16px;
    background: var(--accent-soft); color: var(--soft); font-size: 12.5px; text-align: center;
  }
  .perf-import-compact .perf-drop { flex: 1; padding: 8px 14px; }
  .perf-drop:hover { border-color: var(--accent); }
  .perf-drop-input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
  .perf-import-note { font-size: 11px; color: var(--dim); line-height: 1.5; margin: 8px 2px 0; }
  .perf-clear { color: var(--err); white-space: nowrap; }
  .perf-appt { width: 100%; margin-top: 10px; }
  .perf-appt-toggle { cursor: pointer; font-size: 12px; color: var(--soft); list-style: none; }
  .perf-appt-toggle::-webkit-details-marker { display: none; }
  .perf-appt-toggle::before { content: "+ "; color: var(--dim); }
  .perf-appt[open] .perf-appt-toggle::before { content: "\2212  "; }
  .perf-appt-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
  .perf-appt-input {
    width: 100%; border: 1px solid var(--border); border-radius: var(--r-md); padding: 10px 12px;
    font: inherit; font-size: 12.5px; line-height: 1.5; resize: vertical; background: var(--card); color: var(--ink);
  }
  .perf-appt-form .btn { align-self: flex-start; }

  .perf-calc { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 12px; }
  .perf-calc-toggle { cursor: pointer; font-size: 12px; font-weight: 600; color: var(--soft); list-style: none; }
  .perf-calc-toggle::-webkit-details-marker { display: none; }
  .perf-calc-toggle::before { content: "+ "; color: var(--dim); }
  .perf-calc[open] .perf-calc-toggle::before { content: "\2212  "; }
  .perf-calc-existing { display: flex; align-items: flex-start; gap: 8px; margin-top: 12px; }
  .perf-calc-add { margin-top: 12px; }
  .perf-calc-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; margin-top: 13px; }
  .perf-calc-form { flex: 1; min-width: 0; }
  .perf-calc-fields { display: flex; flex-direction: column; gap: 8px; }
  .perf-calc-row { display: flex; gap: 8px; }
  .perf-calc-remove { background: none; border: 0; padding: 7px 2px 0; cursor: pointer; color: var(--err); font-size: 11.5px; white-space: nowrap; }
  .perf-calc-chips { display: flex; flex-wrap: wrap; gap: 5px; }
  .perf-calc-chip {
    border: 1px solid var(--border); border-radius: 999px; padding: 3px 9px; background: var(--card);
    color: var(--soft); font-size: 11px; cursor: pointer; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  .perf-calc-chip:hover { border-color: var(--accent); color: var(--ink); }
  .perf-calc-chip[hidden] { display: none; }
  .perf-calc-op { font-weight: 700; color: var(--ink); background: var(--accent-soft); }
  .perf-calc-input {
    flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 11px;
    font: inherit; font-size: 12.5px; background: var(--card); color: var(--ink);
  }
  .perf-calc-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
  .perf-calc-unit { border: 1px solid var(--border); border-radius: var(--r-md); padding: 8px 6px; background: var(--card); color: var(--ink); font: inherit; font-size: 12.5px; }
  .perf-calc-hint { font-size: 11px; color: var(--dim); line-height: 1.5; margin: 8px 2px 0; }
  .perf-calc-hint code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

  /* Both perf pickers (metrics + summary-stats) share ONE popover treatment */
  .metrics-picker, .stat-picker-menu {
    position: absolute; right: 0; z-index: 6; margin: 0; padding: 0; background: var(--card);
    border: 1px solid var(--border2); border-radius: 14px; box-shadow: 0 12px 34px oklch(0.2 0 0 / 0.16);
  }
  .metrics-picker { top: calc(100% + 6px); width: 290px; }
  .stat-picker-menu { bottom: calc(100% + 6px); width: 250px; }
  .metrics-picker-head, .stat-picker-head { font-size: 12px; font-weight: 700; letter-spacing: -0.01em; padding: 11px 14px 0; }
  .metrics-picker-hint, .stat-picker-hint {
    font-size: 10px; color: var(--dim); line-height: 1.45; margin: 3px 0 0; padding: 0 14px 9px;
    border-bottom: 1px solid var(--hairline);
  }
  .metrics-picker-list, .stat-picker-list { max-height: 284px; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; padding: 5px; }
  .metrics-picker-row, .stat-pick-row { padding: 6px 7px; border-radius: 7px; }
  .metrics-picker-row:hover, .stat-pick-row:hover { background: var(--inset); }
  .metrics-picker-foot, .stat-picker-foot { display: flex; justify-content: flex-end; padding: 8px 12px 12px; margin: 0; }

  /* metrics-picker-only bits */
  .metrics-picker-row { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 8px; }
  .metrics-check {
    appearance: none; width: 17px; height: 17px; border-radius: 5px; border: 1.5px solid var(--border);
    background: var(--card); cursor: pointer; flex-shrink: 0;
  }
  .metrics-check:checked { background: var(--accent); border-color: var(--accent); }
  .metrics-rename { border: 1px solid transparent; background: transparent; font-size: 12.5px; padding: 4px 6px; border-radius: var(--r-sm); color: var(--ink); }
  .metrics-rename:hover, .metrics-rename:focus { border-color: var(--border2); background: var(--inset); outline: none; }
  .metrics-star { cursor: pointer; color: var(--dim); font-size: 15px; line-height: 1; }
  .metrics-star.is-on { color: var(--accent); }
  .metrics-star-input { position: absolute; opacity: 0; width: 0; height: 0; }
  .metrics-name { font-size: 12.5px; color: var(--ink); cursor: pointer; }

  /* Summary-stats picker (configurable perf-stats row) */
  .perf-stats-head { display: flex; align-items: center; justify-content: space-between; margin: 16px 0 6px; }
  .perf-stats-caption { font-size: 11px; font-weight: 600; color: var(--label); letter-spacing: 0.05em; text-transform: uppercase; }
  .stat-picker { position: relative; }
  .stat-picker > summary { list-style: none; }
  .stat-picker > summary::-webkit-details-marker { display: none; }
  .stat-picker-trigger {
    display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
    font-size: 11px; font-weight: 600; color: var(--soft);
    border: 1px solid var(--border2); border-radius: 20px; padding: 3px 10px; background: var(--card);
  }
  .stat-picker-trigger:hover { border-color: var(--accent-border); color: var(--ink); }
  .stat-pick-row { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 9px; cursor: pointer; }
  .stat-pick-input { position: absolute; opacity: 0; width: 0; height: 0; }
  .stat-pick-box {
    width: 17px; height: 17px; border-radius: 5px; border: 1.5px solid var(--border);
    display: inline-flex; align-items: center; justify-content: center; color: transparent;
  }
  .stat-pick-input:checked ~ .stat-pick-box { background: var(--mc); border-color: var(--mc); color: #fff; }
  .stat-pick-name { font-size: 12.5px; color: var(--ink); }
  .stat-pick-badge:not(:empty) {
    min-width: 18px; height: 18px; border-radius: 5px; background: var(--mc); color: #fff;
    font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; padding: 0 5px;
  }
  .stat-picker.is-full .stat-pick-row:not(:has(.stat-pick-input:checked)) { opacity: 0.4; cursor: not-allowed; }
  .stat-picker.is-full .stat-pick-row:not(:has(.stat-pick-input:checked)):hover { background: transparent; }
}

/* ── KPI sparklines (dashboard + portal) ─────────────── */
@layer components {
  .kpi-trend-cell { display: inline-flex; align-items: center; gap: 8px; }
  .spark { width: 60px; height: 20px; display: block; }
  .spark-delta { font-size: 11px; font-weight: 600; }
  .spark-good { color: var(--ok); }
  .spark-bad  { color: var(--err); }
  .spark-flat { color: var(--dim); }
  .portal-kpi { margin-bottom: 4px; }
  td.kpi-trend { white-space: nowrap; }
}

/* ── Creative Set page (assets, add flow, review, decision) ─────────── */

  /* Share popover — the .filter-menu <details> shell with the .filter-options panel
     (see there) re-anchored right, since it hangs off a control in the set header. */
  .share-pop { right: 0; width: 372px; max-width: calc(100vw - 32px); padding: 15px; gap: 12px; text-align: left; }
  .share-btn { display: inline-flex; align-items: center; gap: 7px; }
  .share-title { font-size: 13.5px; font-weight: 700; letter-spacing: -0.01em; }
  .share-sub { font-size: 11px; color: var(--muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .share-row { display: flex; align-items: center; gap: 8px; }
  .share-url {
    flex: 1; min-width: 0; padding: 8px 10px;
    background: var(--page); border: 1px solid var(--border); border-radius: var(--r-md);
    font-family: var(--mono); font-size: 11px; color: var(--soft);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* Below the app's mobile breakpoint the set header wraps, so the Share button lands on
     the left and a right-anchored panel hangs 200px off the edge. Pin it to the viewport
     instead, clear of the bottom bar — no header-height guess to go stale. */
  @media (max-width: 700px) {
    .share-pop { position: fixed; inset: auto 16px 80px; width: auto; max-width: none; }
    /* Icon only. The word costs 47px, which is exactly what pushed the pre-existing
       "All sets" link off a 375px screen — the summary's aria-label still names it. */
    .share-label { display: none; }
  }
  .share-copy { flex-shrink: 0; padding: 9px 14px; border-radius: var(--r-md); }
  .share-copy.is-copied { background: var(--ok); }
  .share-note { display: flex; align-items: flex-start; gap: 8px; margin: 0; font-size: 11.5px; color: var(--muted); line-height: 1.5; }
  .share-note svg { flex-shrink: 0; margin-top: 2px; color: var(--label); }
  .share-preview { font-weight: 600; color: var(--accent); text-decoration: none; white-space: nowrap; }
  .share-preview:hover { text-decoration: underline; }
@layer components {
  /* Set-page header: back, who it's for, what it is, what state it's in. The overview card
     it replaced said the same three things in a stack above the assets. */
  .cs-head {
    display: flex; align-items: center; gap: 13px; padding: 15px 24px;
    background: var(--card); border-bottom: 1px solid var(--border2);
  }
  .cs-head-title { min-width: 0; margin-right: auto; }
  .cs-head-campaign {
    display: block; font-size: 11.5px; font-weight: 600; color: var(--muted);
    text-decoration: none; margin-bottom: 1px;
  }
  .cs-head-campaign:hover { color: var(--accent); }
  /* ⚠ margin: 0 — the browser's default h1 margin is 0.67em, which pushed the campaign line
     13px off its own title and inflated the bar to 92px. */
  .cs-head h1 { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -0.025em; line-height: 1.15; }
  .cs-head-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

  .cs-body { max-width: 880px; margin: 0 auto; padding: 26px 32px 44px; display: flex; flex-direction: column; gap: 18px; }
  .cs-link { font-size: 13px; font-weight: 700; color: var(--accent); text-decoration: none; }
  .cs-link:hover { text-decoration: underline; }

  .cs-mini-btn {
    background: var(--card); border: 1px solid var(--border); color: var(--muted-strong, #4A4640);
    border-radius: 7px; padding: 5px 12px; font-size: 11.5px; font-weight: 600; cursor: pointer;
    font-family: inherit; white-space: nowrap;
  }
  .cs-mini-btn:hover { background: #F6F3EE; color: var(--ink); }
  .cs-mini-btn--green { border-color: #C5E0CD; color: #2E6E42; }

  /* Locked / editing banners */
  .cs-locked-banner { background: #EAF4EC; border: 1px solid #C5E0CD; border-radius: 10px; padding: 13px 16px; display: flex; align-items: center; gap: 12px; }
  /* `color` feeds the shared icons/lock partial's currentColor — it replaces the #3A8A52
     that used to be hardcoded on that one inline SVG, and --ok is the same green. */
  .cs-locked-icon { width: 28px; height: 28px; border-radius: 50%; background: var(--card); color: var(--ok); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .cs-locked-text { flex: 1; min-width: 0; }
  .cs-locked-title { font-size: 13px; font-weight: 700; color: #2E6E42; }
  .cs-locked-sub { font-size: 11.5px; color: #5C7A63; margin-top: 2px; line-height: 1.5; }
  .cs-feedback-banner { background: #FDF8EE; border: 1px solid #EAD9B4; border-radius: 10px; padding: 13px 16px; display: flex; align-items: flex-start; gap: 12px; }
  .cs-feedback-icon { width: 28px; height: 28px; border-radius: 50%; background: var(--card); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .cs-feedback-text { flex: 1; min-width: 0; }
  .cs-feedback-title { font-size: 13px; font-weight: 700; color: #8A6A3D; }
  .cs-feedback-note { font-size: 13px; color: #4A4640; line-height: 1.55; margin-top: 4px; white-space: pre-line; }
  .cs-editing-strip { background: #FDF8EE; border: 1px solid #EAD9B4; border-radius: 10px; padding: 11px 16px; display: flex; align-items: center; gap: 12px; }
  .cs-editing-text { flex: 1; min-width: 0; font-size: 11.5px; color: #8A6A3D; line-height: 1.5; }

  /* Assets header */
  .cs-assets-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  .cs-assets-head h2 { font-size: 14px; font-weight: 700; margin: 0; letter-spacing: -0.01em; }
  .cs-count { font-size: 11.5px; font-weight: 600; color: var(--dim); }
  .cs-hint { font-size: 11.5px; color: var(--dim); margin: 3px 0 0; line-height: 1.4; }

  /* Add panel */
  .cs-add-panel { background: var(--card); border: 1.5px solid var(--accent-border); border-radius: 12px; padding: 18px 20px; display: flex; flex-direction: column; gap: 14px; box-shadow: 0 6px 22px oklch(0.49 0.18 270 / 0.08); }
  .cs-add-title { font-size: 13px; font-weight: 700; letter-spacing: -0.01em; }
  .cs-add-form { display: flex; flex-direction: column; gap: 8px; }
  .cs-add-hint { font-size: 11.5px; color: var(--muted); line-height: 1.55; margin: 0; }
  .cs-add-hint code { font-family: ui-monospace, monospace; background: #F0ECE6; padding: 0 4px; border-radius: 3px; }
  .cs-mono-textarea { width: 100%; background: #FAF9F6; border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; font-size: 13px; line-height: 1.6; color: var(--ink); font-family: ui-monospace, monospace; outline: none; resize: vertical; }
  .cs-mono-textarea:focus { border-color: var(--accent); background: var(--card); }
  .cs-add-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .cs-parse-note { font-size: 11.5px; font-weight: 600; color: var(--accent); }
  .cs-add-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
  .cs-text-btn { background: transparent; border: none; color: var(--muted); font-size: 12px; font-weight: 600; cursor: pointer; font-family: inherit; padding: 8px 6px; }
  .cs-text-btn:hover { color: var(--ink); }
  .cs-add-blank { display: flex; align-items: center; gap: 10px; margin-top: 4px; flex-wrap: wrap; }
  .cs-num { width: 64px; background: var(--card); border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px; font-size: 12px; font-family: inherit; }
  .cs-drop { border: 1.5px dashed var(--accent-border); background: oklch(0.49 0.18 270 / 0.03); border-radius: 10px; padding: 26px 20px; display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; text-align: center; }
  .cs-drop.is-over { border-color: var(--accent); background: oklch(0.49 0.18 270 / 0.07); }
  .cs-drop-title { font-size: 13px; font-weight: 700; color: var(--ink); }
  .cs-drop-sub { font-size: 11.5px; color: var(--muted); }

  /* Empty state */
  .cs-empty { border: 1.5px dashed #D5CDBF; background: transparent; border-radius: 12px; padding: 40px 20px; display: flex; flex-direction: column; align-items: center; gap: 8px; cursor: pointer; font-family: inherit; width: 100%; }
  .cs-empty:hover { background: #F3F0EA; border-color: #B8AE9C; }
  .cs-empty-plus { font-size: 22px; font-weight: 700; color: var(--accent); line-height: 1; }
  .cs-empty-title { font-size: 13px; font-weight: 700; color: var(--ink); }
  .cs-empty-sub { font-size: 11.5px; color: var(--muted); }

  .cs-rows { display: flex; flex-direction: column; gap: 10px; }

  /* Copy rows sit under their placement. One heading primitive, shared by the
     agency page and the client review table (which scopes its own band). */
  /* Section head — "COPY 18" over a block. (The per-placement group headings it replaced
     are gone: every row names its own placement now, on all three surfaces.) */
  .cs-section-head { display: flex; align-items: baseline; gap: 9px; }

  /* Editable field chrome — every input LOOKS editable */
  .cs-field { display: flex; flex-direction: column; gap: 3px; }
  .cs-field--sm { flex: 0 0 auto; }
  .cs-input { background: #FBFAF7; border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px; font-size: 12px; font-weight: 600; color: var(--ink); font-family: inherit; outline: none; }
  .cs-input:focus { border-color: var(--accent); background: var(--card); }
  .cs-input--variant { width: 58px; text-align: center; color: var(--accent); border-color: var(--accent-border); }
  .cs-input--mono { font-family: ui-monospace, monospace; font-weight: 500; }
  /* field-sizing grows the box to its copy, so a long line is never behind a
     scrollbar you have to drag open. min-height keeps an empty box from collapsing. */
  .cs-textarea { width: 100%; min-height: 38px; field-sizing: content; background: #FAF9F6; border: 1px solid var(--border); border-radius: 7px; padding: 8px 10px; font-size: 13px; line-height: 1.55; color: var(--ink); font-family: inherit; outline: none; resize: vertical; }
  .cs-textarea:focus { border-color: var(--accent); background: var(--card); }

  /* Copy row */
  .cs-copy-row { position: relative; background: var(--card); border: 1px solid var(--border2); border-radius: 10px; padding: 12px 14px; }
  .cs-copy-form { display: flex; flex-direction: column; gap: 9px; }
  .cs-copy-meta { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; padding-right: 78px; }
  .cs-row-actions { position: absolute; top: 12px; right: 12px; display: flex; align-items: center; gap: 2px; }
  .cs-row-actions-edit { display: flex; gap: 2px; }
  /* Sits with the row's controls: informative, so it stays quiet until you look for it. */
  .cs-char-count { font-size: 10.5px; font-weight: 600; color: var(--label); margin-right: 6px; white-space: nowrap; }
  .cs-copy-btn { display: inline-flex; align-items: center; gap: 4px; background: transparent; border: none; cursor: pointer; padding: 4px 5px; color: var(--label); font-family: inherit; }
  .cs-copy-btn:hover { color: var(--accent); }
  .cs-copy-btn .cs-copy-done { display: none; align-items: center; gap: 4px; font-size: 10px; font-weight: 600; color: #3A8A52; }
  .cs-copy-btn.is-copied .cs-copy-idle { display: none; }
  .cs-copy-btn.is-copied .cs-copy-done { display: inline-flex; }
  .cs-icon-btn { background: transparent; border: none; cursor: pointer; padding: 4px; color: var(--label); display: flex; }
  .cs-icon-btn:hover { color: var(--accent); }
  .cs-icon-btn--danger:hover { color: #C24A2E; }
  .cs-icon-form { margin: 0; display: inline-flex; }

  /* Image grid */
  .cs-img-card { background: var(--card); border: 1px solid var(--border2); border-radius: 10px; padding: 14px; display: flex; flex-direction: column; gap: 11px; }
  .cs-img-head { display: flex; align-items: baseline; gap: 9px; }
  /* Tiles are drawn at each image's real shape (an inline aspect-ratio, from the
     blob's analyzed size), so start-align them rather than stretching a short tile
     to match a tall neighbour. The 1/1 below is the fallback for an unanalyzed
     upload and for an empty drop tile. */
  .cs-img-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 12px; align-items: start; }
  .cs-tile-wrap { position: relative; }
  .cs-tile { display: flex; flex-direction: column; gap: 6px; margin: 0; }
  .cs-tile-slot { aspect-ratio: 1 / 1; background: #F1EEE8; border-radius: 8px; display: flex; align-items: center; justify-content: center; overflow: hidden; cursor: pointer; }
  .cs-tile-img { width: 100%; height: 100%; object-fit: contain; display: block; }
  .cs-tile-drop { font-size: 11.5px; color: var(--dim); }
  .cs-tile-label { width: 100%; }
  .cs-tile-dims { font-size: 10.5px; font-weight: 600; color: var(--dim); }
  .cs-tile-del { position: absolute; top: 6px; right: 6px; background: oklch(1 0 0 / 0.9); border: 1px solid var(--border2); border-radius: 6px; cursor: pointer; padding: 3px; color: var(--muted); display: flex; }
  .cs-tile-del:hover { color: #C24A2E; }

  /* Link (video / landing page) row */
  .cs-link-wrap { position: relative; display: flex; gap: 14px; align-items: flex-start; background: var(--card); border: 1px solid var(--border2); border-radius: 10px; padding: 12px 14px; }
  .cs-link-row { display: flex; gap: 14px; flex: 1; min-width: 0; margin: 0; }
  .cs-link-thumb { width: 104px; height: 64px; flex-shrink: 0; background: #F1EEE8; border-radius: 8px; overflow: hidden; display: flex; align-items: center; justify-content: center; cursor: pointer; }
  .cs-link-img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .cs-thumb-drop { font-size: 11.5px; color: var(--dim); }
  .cs-link-fields { display: flex; flex-direction: column; gap: 8px; flex: 1; min-width: 0; }
  .cs-link-fields .cs-input { width: 100%; }
  .cs-link-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
  .cs-open-btn { display: inline-flex; align-items: center; gap: 5px; background: var(--card); border: 1px solid var(--border); color: #4A4640; border-radius: 7px; padding: 7px 12px; font-size: 12px; font-weight: 600; text-decoration: none; white-space: nowrap; }
  .cs-open-btn:hover { background: #F6F3EE; color: var(--ink); }
  .cs-open-btn svg { flex-shrink: 0; opacity: 0.7; }
  .cs-open-btn--dark { background: var(--ink); color: #F8F7F4; border-color: var(--ink); }
  .cs-open-btn--dark:hover { background: #33302C; color: #F8F7F4; }

  /* Send bar */
  .cs-send-bar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; background: #F6F8FF; border: 1px solid #DCE3FA; border-radius: 12px; padding: 14px 18px; }
  .cs-send-icon--ok { width: 26px; height: 26px; border-radius: 50%; background: #EAF4EC; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .cs-send-icon--queue { width: 26px; height: 26px; border-radius: 50%; background: #EBF0FC; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .cs-send-text { flex: 1; min-width: 170px; }
  .cs-send-title { font-size: 13px; font-weight: 700; letter-spacing: -0.01em; }
  .cs-send-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.5; }
  .cs-send-preview { font-size: 12px; font-weight: 600; color: var(--accent); text-decoration: none; white-space: nowrap; }
  .cs-send-bar form { margin: 0; }

  .cs-danger { padding: 6px 2px 0; }
  .cs-danger-btn { background: transparent; border: none; color: #C24A2E; font-size: 11.5px; font-weight: 600; cursor: pointer; font-family: inherit; padding: 4px 0; }
  .cs-danger-btn:hover { text-decoration: underline; }
  .cs-danger form { margin: 0; }

  /* Locked state: soft-disable inputs, hide edit affordances, keep copy button */
  .cs-assets.is-locked .cs-input,
  .cs-assets.is-locked .cs-textarea,
  .cs-assets.is-locked .cs-tile-slot { pointer-events: none; background: #F4F1EB; color: var(--muted); }
  .cs-assets.is-locked .cs-edit-only,
  .cs-assets.is-locked .cs-row-actions-edit { display: none !important; }

  /* ── Client review ─────────────────────────────── */
  .cs-review { display: flex; flex-direction: column; gap: 18px; }
  .cs-review-intro { background: #EBF0FC; border: 1px solid #D9E0F6; border-radius: 10px; padding: 14px 18px; }
  .cs-review-intro-title { font-size: 13px; font-weight: 700; color: #232B66; }
  .cs-review-intro-sub { font-size: 11.5px; color: #4A5178; margin-top: 3px; line-height: 1.55; }
  .cs-review-section { display: flex; flex-direction: column; gap: 12px; }

  /* WHERE | LABEL | COPY. One grid template shared by the header row and every body row,
     so the columns can't drift apart. */
  .cs-copy-table { border: 1px solid var(--border2); border-radius: 10px; overflow: hidden; background: var(--card); }
  .cs-copy-thead, .cs-copy-trow {
    display: grid; grid-template-columns: 150px 52px 1fr; gap: 10px;
    padding: 10px 14px; align-items: start;
  }
  .cs-copy-thead { background: #F4F1EB; border-bottom: 1px solid var(--border2); padding: 9px 14px; }
  .cs-copy-trow { border-bottom: 1px solid #F0ECE6; }
  .cs-copy-trow:last-child { border-bottom: none; }
  .cs-cell-place { font-size: 12.5px; font-weight: 700; color: var(--ink); }
  .cs-cell-var { font-size: 11.5px; font-weight: 700; color: var(--accent); }
  .cs-cell-copy { font-size: 13px; color: #4A4640; line-height: 1.55; white-space: pre-line; }

  .cs-review-imgs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .cs-review-img { margin: 0; display: flex; flex-direction: column; gap: 6px; }
  .cs-review-img-slot { aspect-ratio: 1 / 1; background: #F1EEE8; border-radius: 8px; overflow: hidden; display: flex; align-items: center; justify-content: center; }
  .cs-review-img-slot img { width: 100%; height: 100%; object-fit: contain; }
  .cs-review-img figcaption { font-size: 12px; font-weight: 600; color: #4A4640; }

  .cs-review-media { border: 1px solid var(--border2); border-radius: 10px; overflow: hidden; background: var(--card); }
  .cs-review-still { position: relative; height: 260px; background: var(--ink); display: flex; align-items: center; justify-content: center; }
  .cs-review-still img { width: 100%; height: 100%; object-fit: contain; }
  .cs-review-shot { min-height: 200px; background: #F1EEE8; }
  .cs-review-shot img { width: 100%; display: block; }
  .cs-play-badge { position: absolute; width: 52px; height: 52px; border-radius: 50%; background: oklch(0.2 0 0 / 0.55); display: flex; align-items: center; justify-content: center; }
  .cs-review-media-foot { display: flex; align-items: center; gap: 12px; padding: 12px 15px; border-top: 1px solid #F0ECE6; }
  .cs-review-media-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; color: var(--ink); }
  .cs-review-media-link { font-size: 11.5px; color: var(--dim); margin-top: 2px; font-family: ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* Landing pages: 50/50 portrait preview beside the name + link. */
  .cs-review-page { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; border: 1px solid var(--border2); border-radius: 10px; overflow: hidden; background: var(--card); }
  .cs-review-page-shot { min-width: 0; aspect-ratio: 3 / 4; max-height: 440px; background: #F1EEE8; overflow: hidden; }
  .cs-review-page-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }
  .cs-review-page-info { min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 8px; padding: 16px 18px; border-left: 1px solid #F0ECE6; }
  .cs-review-page-info .cs-review-media-link { white-space: normal; word-break: break-all; }
  @media (max-width: 560px) { .cs-review-page { flex-direction: column; } .cs-review-page-shot { aspect-ratio: 4 / 3; } .cs-review-page-info { border-left: none; border-top: 1px solid #F0ECE6; } }

  /* Comment + decision */
  .cs-comment { background: var(--card); border: 1px solid var(--border2); border-radius: 10px; padding: 16px 18px; }
  .cs-comment label { display: block; font-size: 13px; font-weight: 700; color: var(--ink); margin-bottom: 8px; }
  .cs-optional { color: var(--dim); font-weight: 600; }
  .cs-comment-box { width: 100%; min-height: 76px; background: #FAF9F6; border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; font-size: 13px; line-height: 1.55; color: var(--ink); font-family: inherit; outline: none; resize: vertical; }
  .cs-comment-box:focus { border-color: var(--accent); background: var(--card); }
  .cs-comment-box:invalid:not(:placeholder-shown) { border-color: #C24A2E; }
  .cs-decision-form { display: flex; flex-direction: column; gap: 14px; }
  /* ⚠ Deliberately NOT sticky. It used to float at `bottom: 14px`, which on iOS puts the one
     control a client must be able to hit against a viewport the keyboard is busy resizing —
     the tap lands where the button was, not where it is. It sits at the end of the page now. */
  .cs-decision-bar { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 14px 18px; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; box-shadow: 0 10px 30px oklch(0.2 0 0 / 0.14); }
  .cs-decision-text { flex: 1; min-width: 170px; }
  .cs-decision-title { font-size: 13px; font-weight: 700; letter-spacing: -0.01em; }
  .cs-decision-sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; line-height: 1.5; }
  .cs-btn-ghost { background: var(--card); border: 1px solid var(--border); color: #4A4640; border-radius: 8px; padding: 10px 16px; font-size: 13px; font-weight: 600; cursor: pointer; font-family: inherit; white-space: nowrap; }
  .cs-btn-ghost:hover { background: #F6F3EE; }
  .cs-btn-approve { background: #3A8A52; color: #FFFFFF; border: none; border-radius: 8px; padding: 10px 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; white-space: nowrap; text-decoration: none; display: inline-block; }
  .cs-btn-approve:hover { background: #2F7444; }
  .cs-decision-bar form { margin: 0; }

  .cs-decided { border-radius: 12px; padding: 16px 18px; display: flex; align-items: center; gap: 13px; }
  .cs-decided--ok { background: #EAF4EC; border: 1px solid #C5E0CD; }
  .cs-decided--amber { background: #FDF8EE; border: 1px solid #EAD9B4; }
  .cs-decided-icon { width: 30px; height: 30px; border-radius: 50%; background: var(--card); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .cs-decided--ok .cs-decided-title { font-size: 13px; font-weight: 700; color: #2E6E42; }
  .cs-decided--ok .cs-decided-sub { font-size: 11.5px; color: #5C7A63; margin-top: 2px; }
  .cs-decided--amber .cs-decided-title { font-size: 13px; font-weight: 700; color: #8A6A3D; }
  .cs-decided--amber .cs-decided-sub { font-size: 11.5px; color: #9A7B4D; margin-top: 2px; line-height: 1.5; }
  .cs-review-wait { background: #F3F0EA; border: 1px solid var(--border2); border-radius: 10px; padding: 16px 18px; font-size: 11.5px; color: var(--muted); line-height: 1.5; }

  @media (max-width: 760px) {
    .cs-body { padding: 18px 16px 40px; }
    .cs-head { flex-wrap: wrap; gap: 10px; padding: 14px 16px; }
    .cs-head-title { margin-right: 0; }
    .cs-head-actions { width: 100%; }
    .status-strip { width: 100%; overflow-x: auto; }
    .cs-review-imgs { grid-template-columns: 1fr 1fr; }
    .cs-link-wrap { flex-wrap: wrap; }
  }
  /* ⚠ Below 430px the three columns stack: WHERE and LABEL ride one line above the copy,
     which gets the full width. Squeezing them side by side is what left the copy in a
     two-word gutter before the column became a heading — and this brings the column back. */
  @media (max-width: 430px) {
    .cs-copy-thead { display: none; }          /* the row says both words itself */
    .cs-copy-trow { grid-template-columns: auto 1fr; gap: 2px 8px; }
    .cs-cell-var { justify-self: start; align-self: center; }
    .cs-cell-copy { grid-column: 1 / -1; margin-top: 3px; }
    .cs-copy-meta { padding-right: 60px; }
  }
  @media (max-width: 560px) {
    .cs-review-imgs { grid-template-columns: 1fr 1fr; }
  }
}

/* The `hidden` attribute must beat the display rules on these toggled panels. */
@layer components {
  .cs-add-panel[hidden], .cs-editing-strip[hidden] { display: none; }

  /* The empty state IS the "add something" affordance, so it has nothing to say once the
     add panel is open — and leaving it there left a second, focus-ringed box under the form. */
  .cs-add-panel:not([hidden]) + .cs-empty { display: none; }

  /* File inputs are triggered by their wrapping label — keep them out of the
     layout (mirrors .settings-avatar-input) so they don't clobber the tiles. */
  /* ⚠ position: absolute, so give it a positioned ancestor INSIDE the scroller whenever it
     repeats down a long list. Without one it anchors to .view — the app's outer scroller —
     and every instance adds its own static position to .view's scrollable height. Measured
     once at 905px of phantom scroll below a long page, which dragged the header off-screen
     as you scrolled into it. One `position: relative` on the repeating component fixes it. */
  .cs-visually-hidden { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

  /* Placement = native dropdown + a "Custom…" text box that replaces it. */
  .cs-placement { display: flex; flex-direction: column; gap: 5px; }
  .cs-select { appearance: auto; cursor: pointer; max-width: 200px; height: 28px; }
  .cs-placement-custom { max-width: 200px; }
  .cs-placement-custom[hidden] { display: none; }
}

@layer components {
  /* ── Library ──────────────────────────────────────────────────────────────────
     The brief's palette is the design system's already, to within a percent, so this
     block spends tokens rather than adding a second set of near-identical greys:
     its #FBFAF8 is --inset, #F7F4EF is --hairline, and #DED8CE / #D8D2C8 / #E4DFD5
     are all --border. Only the pale blue glyph tint had no token; see --accent-tint. */

  .lib-back {
    display: flex; align-items: center; gap: 5px;
    font-size: 12px; font-weight: 600; color: var(--muted);
    text-decoration: none; white-space: nowrap;

    & span:first-child { font-size: 15px; }
    &:hover { color: var(--ink); }
  }
  .lib-divider { width: 1px; height: 22px; background: var(--border2); flex-shrink: 0; }
  .lib-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }

  .lib-intro { max-width: 660px; margin: 16px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--muted); }

  .lib-listhead {
    display: flex; align-items: center; gap: 8px; margin: 18px 2px 9px;

    & .lib-budget { margin-left: auto; font-size: 11px; color: var(--dim); }
    & .lib-budget.is-long { color: var(--err-strong); }
    & .lib-manage { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--accent); text-decoration: none; }
  }
  .lib-count {
    font-size: 10px; font-weight: 700; color: var(--soft);
    background: var(--sidebar); border-radius: 999px; padding: 2px 8px;
  }

  /* One track list for the head row and every row, so the columns can't drift. */
  .lib-table {
    --lib-cols: minmax(0, 1fr) 108px 132px 84px 14px;
    max-width: 1180px; min-width: 720px;
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); overflow: hidden;
  }
  .lib-row {
    display: grid; grid-template-columns: var(--lib-cols); gap: 16px; align-items: center;
    padding: 12px 18px; border-top: 1px solid var(--hairline);

    &:hover { background: var(--inset); }
    &:first-child { border-top: 0; }
  }
  .lib-row--head {
    padding: 9px 18px; background: var(--inset); border-top: 0;

    & span { font-size: 9px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--label); }
    &:hover { background: var(--inset); }
  }

  .lib-name {
    display: flex; align-items: center; gap: 12px; min-width: 0; text-decoration: none; color: inherit;
  }
  .lib-tile {
    display: grid; place-items: center; flex-shrink: 0;
    width: 30px; height: 30px; border-radius: 9px;
    background: var(--icon-tile); color: var(--dim);

    &.is-pinned { background: var(--accent-tint); color: var(--accent); }
  }
  .lib-title {
    font-size: 13.5px; font-weight: 700; letter-spacing: -0.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .lib-tag {
    flex-shrink: 0;
    font-size: 8.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--soft); background: var(--icon-tile);
    border: 1px solid var(--border); border-radius: 999px; padding: 2px 7px;
  }
  .lib-meta {
    font-size: 11.5px; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .lib-chevron { color: var(--chevron); }

  /* Two auto-saving toggles per row. The checkbox is the state; everything visible is
     driven off :has(), so there is no JS beyond the auto-save submit. */
  .lib-flags { display: flex; align-items: center; gap: 2px; margin-left: -6px; }
  .lib-toggle {
    display: grid; place-items: center; width: 28px; height: 28px;
    border-radius: var(--r-md); cursor: pointer; color: var(--chevron); opacity: 0.7;

    &:has(.lib-toggle-check:checked) { background: var(--accent-soft); color: var(--accent-ink); opacity: 1; }
    /* The bookmark fills when it is on; the eye never does. */
    &:has(.lib-toggle-check:checked) path[stroke-linejoin] { fill: currentColor; }
    &:hover { background: var(--inset); }
  }
  .lib-toggle-check { position: absolute; opacity: 0; width: 0; height: 0; }

  .lib-empty, .lib-module-empty { padding: 22px 18px; text-align: center; font-size: 12px; color: var(--dim); }

  .lib-table--inherited {
    background: var(--inset); border-style: dashed; box-shadow: none;
  }
  .lib-inherited-row {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    padding: 12px 18px; border-top: 1px solid var(--hairline);

    &:first-child { border-top: 0; }
  }
  .lib-inherited-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
  .lib-preview {
    font-size: 11.5px; color: var(--dim);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* ── Document view ── */
  .lib-allback { display: inline-block; margin: 16px 0 14px; font-size: 12px; font-weight: 600; color: var(--muted); text-decoration: none; }
  .lib-doc-grid { display: grid; grid-template-columns: minmax(0, 1fr) 296px; gap: 20px; align-items: start; max-width: 1180px; }

  .lib-editor {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); overflow: hidden;
  }
  .lib-editor-head {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 18px; border-bottom: 1px solid var(--hairline);
  }
  .lib-editor-title {
    flex: 1; min-width: 0; border: 0; background: transparent;
    font: 800 17px/1.2 inherit; letter-spacing: -0.02em; color: var(--ink);

    &:focus { outline: none; }
  }
  .lib-sync {
    margin: 0; padding: 9px 18px; background: var(--inset);
    border-bottom: 1px solid var(--hairline); font-size: 11.5px; color: var(--soft);
  }
  .lib-body {
    display: block; width: 100%; min-height: 460px; resize: vertical;
    border: 0; padding: 18px; background: transparent;
    font-family: var(--mono); font-size: 12.5px; line-height: 1.75; color: var(--ink);

    &:focus { outline: none; }
  }
  .lib-editor-foot {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 10px 18px; border-top: 1px solid var(--hairline);
    background: var(--inset); font-size: 11px; color: var(--dim);
  }

  .lib-rail { display: flex; flex-direction: column; gap: 14px; }
  .lib-card {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); overflow: hidden;

    & > .section-label { display: block; padding: 13px 16px 4px; }
  }

  .lib-switch-row { border-top: 1px solid var(--hairline); }
  .lib-switch {
    display: flex; align-items: center; gap: 11px; padding: 12px 16px; cursor: pointer;

    & strong { display: block; font-size: 12.5px; color: var(--ink); }
    & span span { display: block; margin-top: 2px; font-size: 11px; line-height: 1.5; color: var(--muted); }
  }
  .lib-switch-text { flex: 1; min-width: 0; }
  .lib-switch-check { position: absolute; opacity: 0; width: 0; height: 0; }
  .lib-switch-track {
    flex-shrink: 0; width: 34px; height: 20px; padding: 2px; border-radius: 999px;
    background: var(--border); transition: background 120ms ease;

    &::after {
      content: ""; display: block; width: 16px; height: 16px; border-radius: 999px;
      background: var(--card); box-shadow: 0 1px 2px oklch(0 0 0 / 0.2);
      transition: transform 120ms ease;
    }
  }
  .lib-switch:has(.lib-switch-check:checked) .lib-switch-track { background: var(--accent); }
  .lib-switch:has(.lib-switch-check:checked) .lib-switch-track::after { transform: translateX(14px); }

  .lib-cedit {
    display: flex; align-items: center; gap: 10px; cursor: pointer;
    padding: 10px 16px 13px 51px; border-top: 1px solid var(--hairline);
    font-size: 12px; font-weight: 600; color: var(--soft);

    & em { font-weight: 400; font-style: normal; color: var(--muted); }
  }

  .lib-details {
    padding: 14px 16px;

    & > .section-label { padding: 0 0 10px; }
  }
  .lib-detail {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    padding: 3px 0; font-size: 11.5px; color: var(--muted);

    & strong { font-weight: 600; color: var(--ink); text-align: right; }
    /* Reads as the value it replaces until you hover it — the row is a fact first and a
       control second. */
    & .lib-detail-link {
      font-weight: 600; color: var(--ink); text-align: right;
      text-decoration: underline dotted var(--border2); text-underline-offset: 3px;

      &:hover { color: var(--accent); text-decoration-color: currentColor; }
    }
  }
  .lib-detail-actions {
    display: flex; gap: 8px; margin-top: 13px; padding-top: 13px;
    border-top: 1px solid var(--hairline);

    & > * { flex: 1; }
    & .btn { width: 100%; }
  }

  /* ── Form ── */
  .lib-form { padding: 18px; margin-top: 16px; max-width: 940px; }
  .lib-label { display: block; margin: 14px 0 6px; font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--label); }
  .lib-name-field { width: 100%; padding: 11px 13px; border: 1px solid var(--border); border-radius: var(--r-lg); font-size: 13px; }
  .lib-form .lib-body { min-height: 300px; border: 1px solid var(--border); border-radius: var(--r-lg); padding: 12px 13px; }
  .lib-form-options { margin-top: 14px; border: 1px solid var(--hairline); border-radius: var(--r-tile); background: var(--inset); }
  .lib-form-options .lib-cedit { padding: 9px 14px; border-top: 1px solid var(--hairline); }
  .lib-form-options .lib-cedit:first-child { border-top: 0; }
  .lib-form-foot { display: flex; align-items: center; gap: 12px; margin-top: 16px; }
  /* Serves both a link (the form page) and a button (the modal's Cancel), so it resets
     the button chrome rather than assuming an anchor. */
  .lib-cancel {
    border: 0; background: transparent; padding: 0; cursor: pointer;
    font: 600 12.5px inherit; color: var(--muted); text-decoration: none;

    &:hover { color: var(--ink); }
  }
  .lib-errors {
    display: flex; flex-direction: column; gap: 4px; margin-bottom: 14px;
    padding: 12px 14px; border-radius: var(--r-tile);
    background: var(--err-tint); color: var(--err-strong); font-size: 12px;
  }

  /* ── Rail module (client + campaign overview) ── */
  .lib-module { overflow: hidden; }
  .lib-module-head { display: flex; align-items: center; justify-content: space-between; padding: 13px 16px 10px; }
  .lib-module-pinlabel {
    display: flex; align-items: center; gap: 7px; padding: 0 16px 4px; color: var(--accent-ink);

    & span { font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap; }
    & path { fill: currentColor; }
  }
  .lib-module-row {
    display: flex; align-items: center; gap: 10px; padding: 9px 16px;
    text-decoration: none; color: inherit;

    &:hover { background: var(--inset); }
    & .lib-tile { width: 26px; height: 26px; border-radius: var(--r-md); }
    & .lib-title { flex: 1; font-size: 12.5px; }
  }
  .lib-module-eye { display: flex; color: var(--accent); }
  .lib-module-foot {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    margin-top: 4px; padding: 11px 16px; background: var(--inset);
    border-top: 1px solid var(--hairline); text-decoration: none;
    font-size: 11.5px; font-weight: 600; color: var(--soft); white-space: nowrap;

    &:hover { background: var(--sidebar); }
  }
  .lib-module-browse { font-size: 11px; color: var(--accent); }
  .lib-module-actions {
    display: flex; align-items: center; gap: 7px;
    padding: 11px 16px 13px; border-top: 1px solid var(--hairline);
  }
  .lib-module-add {
    flex: 1; text-align: center; padding: 7px 10px; border-radius: var(--r-md);
    border: 1px dashed var(--border); font-size: 11.5px; font-weight: 600;
    color: var(--soft); text-decoration: none;

    &:hover { border-color: var(--accent); color: var(--accent); }
  }
  .lib-module-copy {
    padding: 7px 11px; border-radius: var(--r-md); border: 1px solid var(--border);
    background: var(--card); font: 600 11.5px inherit; color: var(--soft); cursor: pointer;

    &:hover { border-color: var(--label); }
  }

  @media (max-width: 900px) {
    .lib-doc-grid { grid-template-columns: minmax(0, 1fr); }
  }
}

@layer components {
  /* ── Library modals (new document, add existing) ──────────────────────────────
     Native <dialog>: it brings the backdrop, Esc, focus trapping and focus return,
     which is why dialog_controller.js is four lines. */
  .lib-modal {
    padding: 0; border: 0; background: transparent; max-width: none; max-height: none;

    &::backdrop { background: oklch(0.22 0.005 68 / 0.42); }
  }
  .lib-modal-card {
    width: 600px; max-width: calc(100vw - 40px);
    /* One decision — how wide — rather than a second card. */
    &.lib-modal-card--narrow { width: 430px; }
    background: var(--card); border: 1px solid var(--border2); border-radius: 18px;
    box-shadow: 0 24px 60px oklch(0.22 0.005 68 / 0.28); overflow: hidden;
  }
  .lib-modal-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
    padding: 16px 20px; border-bottom: 1px solid var(--hairline);
  }
  .lib-modal-title { margin: 0; font-size: 15px; font-weight: 800; letter-spacing: -0.02em; }
  .lib-modal-sub { margin: 3px 0 0; font-size: 11.5px; color: var(--muted); }
  .lib-modal-x {
    border: 0; background: transparent; font-size: 17px; line-height: 1;
    color: var(--dim); cursor: pointer; padding: 0 2px;

    &:hover { color: var(--ink); }
  }

  .lib-modal-list { max-height: 380px; overflow-y: auto; }
  .lib-modal-rowform { margin: 0; }
  .lib-modal-row {
    display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 12px 20px; border: 0; border-bottom: 1px solid var(--hairline);
    background: transparent; font-family: inherit; text-align: left; cursor: pointer;

    &:hover { background: var(--inset); }
  }
  /* The checkbox is a button face, not an <input> — the row IS the toggle, and a real
     checkbox inside a form that submits on click would fight it. */
  .lib-modal-check {
    display: grid; place-items: center; flex-shrink: 0;
    width: 17px; height: 17px; border-radius: 5px;
    border: 1.5px solid var(--border); background: var(--card); color: transparent;

    &.is-on { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
  }
  .lib-modal-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 700; color: var(--ink);
                    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .lib-modal-where { font-size: 10.5px; color: var(--soft); white-space: nowrap; }
  .lib-modal-words { font-size: 10.5px; color: var(--label); white-space: nowrap; }
  .lib-modal-empty { margin: 0; padding: 22px 20px; text-align: center; font-size: 12px; color: var(--dim); }

  .lib-modal-body { padding: 18px 20px; display: flex; flex-direction: column; gap: 14px; }
  .lib-modal-foot {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 13px 20px; border-top: 1px solid var(--hairline); background: var(--inset);
  }
  .lib-modal-body .lib-modal-foot { margin: 4px -20px -18px; }
  .lib-modal-all { font-size: 11.5px; font-weight: 600; color: var(--accent); text-decoration: none; }

  .lib-kinds { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .lib-kind {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 14px 8px; border-radius: var(--r-tile); border: 1.5px solid var(--border2);
    font-size: 11.5px; font-weight: 600; color: var(--soft); text-align: center;

    &.is-on { border-color: var(--accent); background: var(--accent-tint); color: var(--accent-ink); }
    /* Drawn, not offered: `kind` and its CHECK constraint already exist, so switching
       these on later is additive rather than a migration. */
    &.is-off { opacity: 0.45; }
    & em { font-style: normal; font-size: 8.5px; font-weight: 700; letter-spacing: 0.08em;
           text-transform: uppercase; color: var(--label); }
  }
  .lib-body--modal { min-height: 170px; border: 1px solid var(--border); border-radius: var(--r-lg); padding: 12px 13px; }
}

/* ── Queue (/queue) ───────────────────────────────────────────────────────────
   The full-page queue. Throughput is the whole point: the four disposition
   targets sit at the same x-position in every row, so a backlog is set by
   travelling down one column. Nothing here re-renders on a click — the radio
   commits visually before the request leaves, and the counts are the only
   thing JS touches. Selection tint, the expanded editor, the schedule-date
   field and the batch bar are all :has() off real form controls. */
@layer components {
  .q-toolbar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 16px 24px 0; flex-shrink: 0;
  }
  .q-toolbar .filter-menu { margin-left: auto; }

  /* Content column: left-aligned, matching the Clients roster, not centred. */
  .q .campaigns-body { padding: 20px 24px 32px; }
  .q-list { display: flex; flex-direction: column; gap: 16px; max-width: 880px; }

  .q-banner {
    display: flex; align-items: center; gap: 12px; max-width: 880px; margin-bottom: 16px;
    padding: 12px 16px; border-radius: var(--r-xl);
    background: var(--ok-tint); border: 1px solid #BFE3CF;
    font-size: 13.5px; font-weight: 600; color: var(--ok-strong);
    animation: fadeIn 0.15s ease;
  }
  .q-banner-tick {
    width: 22px; height: 22px; flex-shrink: 0; border-radius: 50%;
    background: var(--ok); color: #FFFFFF; font-size: 12px;
    display: flex; align-items: center; justify-content: center;
  }

  .q-selectall {
    display: flex; align-items: center; gap: 12px;
    max-width: 880px; padding: 0 4px 12px;
  }
  .q-check-wrap { display: flex; align-items: center; gap: 12px; cursor: pointer;
                  font-size: 12.5px; font-weight: 600; color: var(--soft); }
  .q-legend { margin-left: auto; display: flex; gap: 14px; }
  .q-legend-item { display: inline-flex; align-items: center; gap: 5px;
                   font-size: 11px; font-weight: 600; color: var(--dim); }

  /* One shared checkbox for row, group and select-all. */
  .q-check {
    appearance: none; width: 20px; height: 20px; margin: 0; flex-shrink: 0; cursor: pointer;
    border: 1.5px solid var(--border); border-radius: 6px; background: var(--card);

    &:checked {
      border-color: var(--accent);
      background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' stroke='white' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
    }
    &:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  }

  /* ── Client group card ── */
  .q-group {
    background: var(--card); border: 1px solid var(--border2);
    border-radius: var(--r-card); overflow: hidden; box-shadow: var(--shadow-sm);
  }
  .q-group-head {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 14px 18px; background: var(--page); border-bottom: 1px solid var(--border2);
  }
  .q-group-name { min-width: 0; margin-right: auto; }
  .q-group-title { font-size: 15px; font-weight: 600; letter-spacing: -0.015em; color: var(--ink); }
  .q-group-sub { font-size: 11.5px; color: var(--dim); margin-top: 1px; }
  .q-group-send { margin: 0; }
  .q-group-send .btn { border-radius: 999px; padding: 8px 16px; font-size: 12.5px;
                       background: var(--card); border: 1px solid var(--border); color: var(--soft);
                       &:hover { border-color: var(--label); background: var(--page); } }

  /* ── Row ── */
  .q-expand { display: none; }
  .q-row { position: relative; border-top: 1px solid var(--hairline);
           &:first-child { border-top: none; } }
  .q-row-main { display: flex; align-items: flex-start; gap: 12px; padding: 14px 18px; }

  .q-msg { flex: 1; min-width: 0; display: block; cursor: pointer; }
  .q-body {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    font-size: 14px; font-weight: 500; line-height: 1.5; text-wrap: pretty; color: var(--ink);
  }
  .q-meta { display: block; margin-top: 3px; font-size: 11.5px; color: var(--dim); }

  .q-chevron {
    width: 28px; height: 28px; flex-shrink: 0; border-radius: 50%; cursor: pointer;
    display: flex; align-items: center; justify-content: center; color: var(--dim);
    &:hover { background: var(--sidebar); }
  }

  /* The keyboard cursor is a left rail, and is a separate idea from selection —
     a row can be both. */
  .q-row.is-cursor { box-shadow: inset 3px 0 0 var(--accent); }

  /* Selection tint and the open state follow the controls directly — no restream. */
  .q-row:has(.q-select:checked) { background: var(--accent-soft); }
  .q-row:has(.q-expand:checked) .q-body { -webkit-line-clamp: unset; }
  .q-row:has(.q-expand:checked) .q-chevron { transform: rotate(180deg); }
  /* A held row dims where it sits. It must NOT leave the list: a row that
     vanishes shifts every row under a cursor travelling down the column. */
  .q-row:has(.q-disp-hold .q-disp-input:checked) .q-msg { opacity: 0.55; }

  /* ── The disposition column ── */
  .q-disp {
    display: flex; gap: 2px; margin: 0; padding: 3px; border: none; flex-shrink: 0;
    background: var(--sidebar); border-radius: 999px;
  }
  .q-disp-target {
    width: 30px; height: 26px; border-radius: 999px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    color: var(--soft); transition: background 0.1s ease;
    &:hover { color: var(--ink); }
    &:has(:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }
  }
  /* Hidden to the eye, present to a screen reader and to the keyboard. Zeroing
     width/height (or opacity alone) drops a control out of the accessibility
     tree, which would cost the radiogroup its whole point. */
  .q-disp-input {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .q-disp-target:has(.q-disp-input:checked) { box-shadow: 0 1px 2px oklch(0.22 0.005 68 / 0.10); }
  .q-disp-send:has(:checked)     { background: var(--ok-tint);     color: var(--ok-strong); }
  .q-disp-schedule:has(:checked) { background: var(--accent-soft); color: var(--accent-ink); }
  .q-disp-hold:has(:checked)     { background: var(--card);        color: var(--muted); }
  .q-disp-record:has(:checked)   { background: var(--card);        color: var(--ink); }

  .q-legend-item.q-disp-send     { color: var(--ok-strong); }
  .q-legend-item.q-disp-schedule { color: var(--accent-ink); }
  .q-legend-item.q-disp-record   { color: var(--soft); }

  /* ── Expanded editor ── */
  .q-editor, .q-remove-form { display: none; }
  .q-row:has(.q-expand:checked) .q-editor,
  .q-row:has(.q-disp-schedule .q-disp-input:checked) .q-editor,
  .q-row:has(.q-expand:checked) .q-remove-form { display: block; }

  .q-editor { margin: 0 18px 2px 50px; animation: fadeIn 0.15s ease; }
  .q-field-label { display: block; font-size: 12px; font-weight: 600; color: var(--soft); margin-bottom: 7px; }
  .q-fields { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 14px; }
  .q-textarea {
    width: 100%; padding: 11px 14px; border: 1px solid var(--border); border-radius: var(--r-lg);
    font: inherit; font-size: 14px; line-height: 1.6; background: var(--card); color: var(--ink);
    resize: vertical; outline: none;
    &:focus { border-color: var(--accent); box-shadow: 0 0 0 3px oklch(0.4941 0.1841 270.5 / 0.16); }
  }
  .q-editor input[type="date"] {
    padding: 10px 13px; border: 1px solid var(--border); border-radius: var(--r-lg);
    font: inherit; font-size: 13.5px; background: var(--card); color: var(--ink); outline: none;
    &:focus { border-color: var(--accent); box-shadow: 0 0 0 3px oklch(0.4941 0.1841 270.5 / 0.16); }
  }
  .q-date-send { background: var(--accent-soft); border-color: var(--accent-border);
                 color: var(--accent-ink); font-weight: 600; }
  .q-origin {
    display: inline-block; padding: 10px 14px; border: 1px solid var(--border2);
    border-radius: var(--r-lg); background: var(--page); font-size: 13.5px; color: var(--soft);
  }

  .q-remove-form { margin: 0 18px 14px 50px; }
  .q-remove {
    display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px;
    border: none; border-radius: 999px; background: none; cursor: pointer;
    font-size: 12.5px; font-weight: 600; color: var(--err);
    &:hover { background: var(--err-tint); }
  }

  /* ── Sent view rows (read-only history) ── */
  .q-row--sent .q-msg { cursor: default; }

  /* ── Batch bar ── */
  .q-batch-form { display: none; }
  .q-batch {
    position: absolute; left: 50%; bottom: 24px; z-index: 30;
    max-width: calc(100% - 32px);
    display: flex; align-items: center; gap: 8px;
    padding: 9px 12px 9px 20px; border-radius: 999px;
    background: var(--ink); color: var(--on-accent);
    box-shadow: 0 12px 32px oklch(0.22 0.005 68 / 0.28);
    opacity: 0; transform: translate(-50%, 12px); pointer-events: none;
    transition: opacity 0.18s ease, transform 0.18s ease;
  }
  .q:has(.q-select:checked) .q-batch { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
  .q-batch-count { font-size: 13px; font-weight: 700; white-space: nowrap; }
  .q-batch-divider { width: 1px; height: 18px; background: oklch(0.9761 0.0041 91.4 / 0.2); }
  .q-batch-btn {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    padding: 8px 15px; border: none; border-radius: 999px; cursor: pointer;
    background: oklch(0.9761 0.0041 91.4 / 0.14); color: var(--on-accent);
    font: inherit; font-size: 12.5px; font-weight: 600; list-style: none;
    &:hover { background: oklch(0.9761 0.0041 91.4 / 0.26); }
    &::-webkit-details-marker { display: none; }
  }
  .q-batch-clear { background: none; border: none; cursor: pointer; color: var(--label);
                   font-size: 15px; line-height: 1; padding: 2px 6px; }
  .q-more { position: relative; }
  .q-more-options { right: 0; bottom: calc(100% + 8px); top: auto; width: 216px; padding: 6px; }
  .q-more-item {
    display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
    padding: 9px 11px; border: none; border-radius: 9px; background: none; cursor: pointer;
    font: inherit; font-size: 13px; color: var(--ink);
    &:hover { background: var(--sidebar); }
    &.is-destructive { color: var(--err); &:hover { background: var(--err-tint); } }
  }
  .q-more-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
  .q-dot-schedule { background: var(--accent); }
  .q-dot-record { background: var(--dim); }
  .q-more-divider { height: 1px; background: var(--sidebar); margin: 5px 0; }

  /* ── Empty state ── */
  .q-empty {
    max-width: 880px; padding: 44px 28px; text-align: center;
    background: var(--card); border: 1px dashed var(--chevron); border-radius: var(--r-card);
  }
  .q-empty-icon {
    width: 56px; height: 56px; margin: 0 auto 16px; border-radius: var(--r-card);
    background: var(--sidebar); color: var(--dim);
    display: flex; align-items: center; justify-content: center;
  }
  .q-empty-title { font-size: 16px; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 7px; }
  .q-empty-body { max-width: 340px; margin: 0 auto; font-size: 13px; line-height: 1.6;
                  color: var(--soft); text-wrap: pretty; }
  .q-empty-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 18px; }
  .q-quiet-link { font-size: 12.5px; font-weight: 600; color: var(--muted); padding: 10px 6px;
                  &:hover { color: var(--ink); } }

  .q-short { display: none; }
}

@media (max-width: 700px) {
  @layer components {
    .q-toolbar { padding: 12px 16px 0; }
    .q .campaigns-body { padding: 16px 16px 96px; }
    .q-long { display: none; }
    .q-short { display: inline; }
    .q-legend { display: none; }
    .q-group-head, .q-row-main { padding: 14px; }

    /* Five segments don't fit 375px: the strip scrolls rather than the page. */
    .q-toolbar .seg-filter { max-width: 100%; overflow-x: auto; }

    /* The column moves to its own line, aligned under the message rather than
       the checkbox, and grows to clear a 44px touch target. `order` keeps the
       chevron up on the message line; the width must subtract its own indent,
       or the row is 32px wider than the page. */
    .q-row-main { flex-wrap: wrap; }
    .q-chevron { order: 1; width: 44px; height: 40px; border-radius: 999px; }
    .q-disp {
      order: 2; width: calc(100% - 32px); margin: 10px 0 0 32px;
      justify-content: space-between;
    }
    .q-disp-target { width: 48px; height: 40px; }
    .q-editor, .q-remove-form { margin-left: 14px; margin-right: 14px; }
    .q-batch { bottom: 92px; }
  }
}

@media (prefers-reduced-motion: reduce) {
  @layer components {
    .q-banner, .q-editor { animation: none; }
    .q-batch { transition: none; }
  }
}

/* ── Docket ───────────────────────────────────────────────────────────────────
   The sweep, its ledger, and the actions registry. The brief's palette is the
   design system's already: its canvas #F8F7F4 is --page, #E8E3DC is --border2,
   #1C1A18 is --ink, #3D52C8 is --accent and #B8862E is --badge-amber. Only its
   success green (#2F9E6E) has no token, and --ok is a percent away — one shade
   is not worth a thirteenth colour variable.

   ⚠ This column is CENTRED, unlike the Queue's, which is deliberately left
   aligned to match the Clients roster. A sweep is one card you look at; a queue
   is a list you scan down. */
@layer components {
  .dk-column { max-width: 620px; margin: 0 auto; padding: 22px 0 60px;
               display: flex; flex-direction: column; gap: 14px; }

  /* The day, and how much of it is left */
  .dk-date { font-size: 19px; font-weight: 800; letter-spacing: -0.025em; color: var(--ink); }
  .dk-remaining { margin-top: 6px; font-size: 12.5px; font-weight: 700; color: var(--soft); }
  .dk-dots { display: flex; gap: 4px; margin-top: 12px; }
  .dk-dot-bar { flex: 1; height: 4px; border-radius: 2px; background: var(--border2);
                &.is-passed { background: var(--accent); }
                &.is-current { background: var(--ink); } }

  /* The proposal */
  .dk-card { background: var(--card); border: 1px solid var(--border2); border-radius: 18px;
             padding: 24px; box-shadow: var(--shadow-sm); }
  .dk-card-head { display: flex; align-items: center; gap: 12px; }
  /* ⚠ min-width: 0 or the flex item refuses to shrink and the ellipsis never fires. */
  .dk-where { min-width: 0; flex: 1; font-size: 14.5px; font-weight: 700; color: var(--ink);
              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dk-title { margin-top: 16px; font-size: 20px; font-weight: 800; letter-spacing: -0.025em; color: var(--ink); }
  /* The only two free-flowing blocks on the page. */
  .dk-body { margin-top: 6px; font-size: 14px; line-height: 1.5; color: var(--soft); text-wrap: pretty; }
  .dk-why { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--hairline); }
  .dk-why-body { margin-top: 6px; font-size: 14px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
  .dk-again { display: block; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--hairline);
              font-size: 12.5px; color: var(--amber-ink); text-decoration: none;
              &:hover { text-decoration: underline; } }

  .dk-verdict { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
                font-weight: 600; color: var(--muted); white-space: nowrap; }
  .dk-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
  /* Never colour alone: each dot sits beside its own word. */
  .dk-verdict--approved { color: var(--accent); }
  .dk-verdict--executed { color: var(--ok); }
  .dk-verdict--dismissed { color: var(--muted); }

  /* Decide. Approve is the only filled button on the screen. */
  .dk-controls { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
  /* Undo is the one control here that is still a form of its own; .dk-controls stretches
     it to row height and this is what lets the .dk-btn inside fill that. */
  .dk-form { display: flex; }
  .dk-btn { display: flex; align-items: center; justify-content: center; width: 100%;
            min-height: 48px; padding: 0 20px; border-radius: 999px; border: 1px solid transparent;
            font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
            background: var(--card); color: var(--ink); white-space: nowrap;
            transition: background 120ms ease, border-color 120ms ease; }
  .dk-btn--primary { background: var(--accent); color: #fff; box-shadow: 0 4px 14px oklch(from var(--accent) l c h / 0.26);
                     &:hover { background: var(--accent-ink); } }
  .dk-btn--outline { border-color: var(--border); &:hover { background: var(--inset); } }
  .dk-btn--ghost { border-color: var(--border2); color: var(--soft); &:hover { background: var(--inset); } }
  .dk-btn--quiet { border-color: var(--border2); color: var(--muted); font-weight: 600;
                   &:hover { background: var(--inset); color: var(--ink); } }
  .dk-btn--dark { background: var(--ink); color: var(--page); &:hover { background: #000; } }
  .dk-decide { list-style: none;
               & > summary { list-style: none; &::-webkit-details-marker { display: none; } } }
  /* ⚠ No :not() here. It used to exempt the dismiss drawer, and its (0,2,0) silently beat
     the mobile rule below that gives every control its own row — which had therefore never
     worked. Approve leads, so it is the one that takes the extra width. */
  .dk-controls > * { flex: 1; }
  .dk-decide--approve { flex: 1.4; }

  /* The note drawer takes the whole row and hides every other control — including the
     OTHER drawer, which is what keeps two of them from being open at once. So the proposal
     stays readable above it and there is exactly one thing to answer.
     ⚠ Excluding .dk-decide[open] rather than .dk-decide: exempt them both and the drawer
     you didn't open stays sitting there, live, beside the one you did. */
  .dk-decide[open] { flex: 1 0 100%;
                     & > summary { display: none; } }
  .dk-controls:has(.dk-decide[open]) > *:not(.dk-decide[open]) { display: none; }
  .dk-drawer { background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
               padding: 16px; }
  .dk-drawer-label { display: block; font-size: 13.5px; font-weight: 700; color: var(--ink); }
  .dk-optional { font-weight: 500; color: var(--dim); }
  /* ⚠ font-weight after `font: inherit`, and load-bearing: the textarea sits inside its
     own <label> (which is how it gets away with having no id), and .dk-drawer-label is 700. */
  .dk-note { width: 100%; margin-top: 10px; min-height: 64px; padding: 10px 12px;
             background: var(--page); border: 1px solid var(--border); border-radius: var(--r-lg);
             font: inherit; font-size: 13.5px; font-weight: 400; color: var(--ink); resize: vertical;
             &:focus { outline: none; background: var(--card); border-color: var(--accent);
                       box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.16); } }
  .dk-drawer-foot { display: flex; gap: 10px; margin-top: 12px;
                    & > *:first-child { flex: 1; } & > *:last-child { flex: 1.4; } }
  .dk-drawer-hint { margin-top: 10px; text-align: center; font-size: 12px; color: var(--soft); }

  /* Written by the controller from the buttons actually rendered. */
  .dk-keys { text-align: center; font-size: 12px; color: var(--soft); }
  .dk-column:has(.dk-decide[open]) .dk-keys { visibility: hidden; }

  /* The end of a sweep */
  .dk-receipt { background: var(--card); border: 1px solid var(--border2); border-radius: 18px;
                overflow: hidden; box-shadow: var(--shadow-sm); }
  .dk-receipt-top { padding: 28px 24px; }
  .dk-receipt-head { display: flex; align-items: center; gap: 10px; }
  .dk-check { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
              background: var(--ok); color: #fff; }
  .dk-receipt-title { font-size: 22px; font-weight: 800; letter-spacing: -0.03em; color: var(--ink); }
  .dk-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 18px; }
  .dk-tile { background: var(--page); border: 1px solid var(--border2); border-radius: 12px;
             padding: 14px; display: flex; flex-direction: column; gap: 2px; }
  .dk-tile-num { font-size: 26px; font-weight: 800; color: var(--ink); }
  .dk-tile-num--approved { color: var(--accent); }
  .dk-tile-label { font-size: 12px; font-weight: 600; color: var(--soft); }
  .dk-receipt-foot { display: flex; flex-wrap: wrap; gap: 12px; align-items: center;
                     justify-content: space-between; padding: 14px 24px;
                     background: var(--inset); border-top: 1px solid var(--hairline); }
  .dk-receipt-note { font-size: 13px; color: var(--soft); }
  .dk-receipt-actions { display: flex; gap: 10px;
                        & .dk-btn { width: auto; min-height: 40px; font-size: 13px; } }

  /* History */
  .dk-filters { display: flex; align-items: center; justify-content: space-between; gap: 12px;
                flex-wrap: wrap; }
  .dk-day-group { margin-top: 18px; }
  .dk-day-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
  .dk-day-label { font-size: 14px; font-weight: 800; color: var(--ink); }
  .dk-day-count { font-size: 12px; color: var(--muted); }
  .dk-log { background: var(--card); border: 1px solid var(--border2); border-radius: 14px;
            overflow: hidden; box-shadow: var(--shadow-sm); }
  .dk-log-row { display: flex; align-items: center; gap: 12px; padding: 12px 16px; cursor: pointer;
                border-bottom: 1px solid var(--hairline);
                &:last-child { border-bottom: none; }
                &:hover { background: var(--inset); } }
  .dk-log-main { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
  .dk-log-title { font-size: 13px; font-weight: 600; color: var(--ink);
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dk-log-where, .dk-log-note { font-size: 11.5px; color: var(--soft);
                                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dk-log-note { font-style: italic; }
  .dk-log-outcome { display: flex; align-items: center; gap: 10px; white-space: nowrap; }
  .dk-log-time { font-family: var(--mono); font-size: 11.5px; color: var(--soft); }
  .dk-truncated { margin-top: 16px; text-align: center; font-size: 12.5px; color: var(--soft); }

  /* History detail */
  .dk-back { display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
             font-size: 13px; font-weight: 600; color: var(--soft); text-decoration: none;
             &:hover { color: var(--ink); } }
  .dk-trail { background: var(--card); border: 1px solid var(--border2);
              border-radius: var(--r-card); padding: 18px 20px;
              box-shadow: var(--shadow-sm); }
  .dk-final { font-size: 13px; line-height: 1.5; color: var(--soft); text-align: center;
              text-wrap: pretty; padding: 0 12px; }
  .dk-trail-row { display: grid; grid-template-columns: 96px 8px 1fr; align-items: center;
                  gap: 10px; margin-top: 10px; font-size: 13px; color: var(--ink); }
  .dk-trail-time { font-family: var(--mono); font-size: 11.5px; color: var(--soft); }
  .dk-trail-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
  .dk-trail-dot--proposed { background: var(--badge-amber); }
  .dk-trail-dot--approved { background: var(--accent); }
  .dk-trail-dot--executed { background: var(--ok); }
  .dk-trail-text { min-width: 0; overflow-wrap: anywhere; }
  /* A fourth child of the 3-column row: pinned to column 3, so auto-placement drops it on
     an implicit second row under the text. align-items centres each item within its OWN
     row track, which is how the time and dot stay level with the first line rather than
     drifting to the middle of a three-line note. */
  .dk-trail-note { grid-column: 3; min-width: 0; margin-top: 2px; font-size: 12.5px;
                   line-height: 1.45; color: var(--soft); text-wrap: pretty;
                   overflow-wrap: anywhere; }
  .dk-requeue { width: 100%; }

  /* ── Actions — the registry table ──
     One surface under the header. The 16px gap matches .clients-table, so Actions sits
     level with Clients and Campaigns. */
  .dk-table, .dk-empty { max-width: 940px; margin: 16px 0 0; }

  .dk-table {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    overflow: hidden; box-shadow: var(--shadow-sm);
    /* The fixed columns (400px), gaps (48px) and padding (44px) need 492px; below that the
       title's minmax(0,…) collapses to nothing and the head text paints over its neighbour.
       Floor the table and let .campaigns-body scroll it — the same answer .campaigns-table
       already gives with its own min-width. 680 = 492 + room for the title. */
    min-width: 680px;
  }
  .dk-row {
    display: grid; grid-template-columns: minmax(0, 2.2fr) 190px 130px 80px;
    gap: 16px; align-items: center;
    padding: 13px 22px; border-bottom: 1px solid var(--hairline);
    transition: background .12s ease; cursor: pointer;
    &:last-child { border-bottom: 0; }
    &:hover { background: var(--inset); }
  }
  .dk-row--head {
    background: var(--page); border-bottom: 1px solid var(--border2); cursor: default;
    font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--label);
    &:hover { background: var(--page); }
  }
  .dk-row.is-archived { color: var(--dim); & .dk-title { color: var(--muted); } }
  .dk-title {
    font-size: 14px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* A button, not a span — that is also what stops the click reaching row-link, which
     already ignores clicks inside buttons (the same split the Archive button relies on). */
  .dk-slug {
    font-family: var(--mono); font-size: 11.5px; color: var(--soft);
    background: var(--hairline); padding: 4px 10px; border-radius: 7px;
    border: none; cursor: pointer;
    &:hover { background: var(--border2); color: var(--ink); }
  }
  .dk-slug .dk-slug-done { display: none; color: var(--ok-strong); }
  .dk-slug.is-copied .dk-slug-label { display: none; }
  .dk-slug.is-copied .dk-slug-done { display: inline; }
  .dk-updated { font-size: 12px; font-weight: 500; color: var(--dim); }
  .dk-delete-cell { text-align: right; }
  .dk-delete-cell form { display: inline; }
  .dk-delete {
    background: none; border: 0; padding: 6px 0 6px 12px; cursor: pointer;
    font-size: 12px; font-weight: 500; color: var(--soft);
    &:hover { color: var(--err); }
  }
  /* !important because .dk-delete's own &:hover outranks a second flat class. */
  .dk-restore { color: var(--accent) !important; }

  .dk-empty {
    background: var(--card); border: 1px dashed var(--border); border-radius: var(--r-card);
    padding: 34px 26px; font-size: 13.5px; color: var(--soft);
  }

  .dk-archived { margin-top: 16px; }
  .dk-archived-toggle { display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
                        font-size: 12.5px; font-weight: 600; color: var(--soft); cursor: pointer;
                        list-style: none;
                        &::-webkit-details-marker { display: none; }
                        & svg { transition: transform 140ms ease; } }
  .dk-archived[open] .dk-archived-toggle svg { transform: rotate(180deg); }

  /* Actions — the form */
  .dk-form-column { max-width: 620px; padding: 22px 0 60px; }
  .dk-form-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
  .dk-form-title { font-size: 22px; font-weight: 800; letter-spacing: -0.025em; color: var(--ink); }
  .dk-form-context { font-size: 12.5px; color: var(--soft); }
  /* No max-width: .dk-form-column already caps this at 620px. */
  .dk-action-card {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    overflow: hidden; box-shadow: var(--shadow-sm); margin: 16px 0 0;
  }
  .dk-form-body { padding: 26px 26px 22px; display: flex; flex-direction: column; }
  .dk-label { font-size: 12px; font-weight: 600; color: var(--ink-2, var(--soft)); margin-bottom: 6px; }
  /* ⚠ A sibling rule, NOT a `gap` on .dk-form-body — gap can't tell a label from its own
     field apart from a field from the next label, and it was that missing distinction that
     glued every label to the box above it. Space goes above a label only when something
     precedes it, so the first one needs no exception and a field added later can't forget
     a wrapper it doesn't have. */
  .dk-form-body > * + .dk-label { margin-top: 20px; }
  /* Scoped: .field-help is a shared primitive with its own margins elsewhere. Here the
     label above already provides the gap. */
  .dk-form-body .field-help { margin: 0 0 6px; }
  .dk-form-foot {
    padding: 16px 26px; background: var(--page); border-top: 1px solid var(--border2);
    display: flex; align-items: center; gap: 10px;
  }
  .dk-cancel {
    color: var(--ink); text-decoration: none; padding: 10px 16px; border-radius: 999px;
    font-size: 13.5px; font-weight: 600;
    &:hover { background: var(--hairline); color: var(--ink); }
  }
  /* The validation messages verbatim. It carries [autofocus], which Turbo honours after
     the 422 re-render, so the &:focus outline would otherwise ring the whole box. */
  .dk-errors {
    background: var(--err-field, #FDF6F4); border: 1px solid #F0CFC6; border-radius: 14px;
    /* No margin-bottom: the label after it takes its own 20px from the sibling rule above. */
    padding: 15px 18px; display: flex; flex-direction: column; gap: 5px;
    & strong { font-size: 13.5px; font-weight: 700; color: var(--err-strong); letter-spacing: -0.01em; margin-bottom: 4px; }
    & span { font-family: var(--mono); font-size: 12px; line-height: 1.5; color: #8A4030; }
    &:focus { outline: none; }
  }
  .dk-field { width: 100%; padding: 11px 13px; background: var(--page);
              border: 1px solid var(--border); border-radius: var(--r-lg);
              font: inherit; font-size: 13.5px; color: var(--ink);
              &:focus { outline: none; background: var(--card); border-color: var(--accent);
                        box-shadow: 0 0 0 3px oklch(from var(--accent) l c h / 0.16); }
              /* The styling IS the "locked" label — a caption would only repeat it. */
              &:disabled { background: var(--hairline); color: var(--soft); cursor: default; } }
  .dk-field--mono { font-family: var(--mono); font-size: 12.5px; }
  .dk-field--area { min-height: 130px; resize: vertical; line-height: 1.5; }
  /* Disabled until something changes, and visibly so — an inert button that looks live
     is worse than one that looks inert. */
  .dk-save:disabled { background: var(--hairline); color: var(--dim); box-shadow: none; cursor: default; }
  .dk-dirty { margin-left: auto; font-size: 12.5px; color: var(--dim);
              &.is-dirty { color: var(--amber-ink); font-weight: 600; } }
}

@media (max-width: 700px) {
  @layer components {
    .dk-column, .dk-form-column { padding: 14px 0 96px; }
    .dk .campaigns-body { padding: 0 16px 96px; }
    /* No keyboard to advertise. */
    .dk-keys { display: none; }
    .dk-filters { flex-direction: column; align-items: stretch; }
    .dk-filters .filter-menu, .dk-filters .filter-pill { width: 100%; }
    /* Every pill keeps its 48px and its whole row: nothing here goes below 44. */
    .dk-controls > * { flex: 1 0 100%; }
    .dk-trail-row { grid-template-columns: 88px 8px 1fr; }
  }
}

/* ── Calls ──
   The list of recorded calls, and one call's record. Built on the campaigns dashboard
   table (.campaigns-table / .campaign-row / .client-chip) and on the .status-menu
   popover, the same way Asset Approvals was — only the assignment pill and the detail
   page's cards are new.

   ⚠ .campaigns-table-wrap is the table to build on, NOT .dk-table: the wrap keeps
   overflow visible precisely so a per-row dropdown can open past it, and .dk-table sets
   overflow: hidden, which would clip the assignment menu on every row. */
@layer components {
  .calls-table td { vertical-align: middle; }
  /* Never colour alone — the sentence says what failed; this only makes it findable. */
  .calls-sync-failed { color: #C8452F; }
  .call-when { color: var(--soft); font-size: 11.5px; white-space: nowrap; }
  .call-guests { color: var(--soft); font-size: 11.5px; max-width: 260px; overflow: hidden; text-overflow: ellipsis; }
  .call-client-cell { white-space: nowrap; }

  /* An ignored call is still listed under All — that is the only way back from a
     mis-click — so it reads as answered-and-set-aside rather than as work. */
  .call-row--ignored .campaign-name, .call-row--ignored .call-guests { opacity: 0.55; }

  /* The assignment control. Assigned reads as a plain chip; unassigned reads as an empty
     slot asking to be filled — dashed, not coloured, because "nobody has filed this" is
     an absence rather than a warning, and most calls start here. */
  .call-assign-pill {
    display: inline-flex; align-items: center; gap: 7px; padding: 4px 8px;
    border-radius: 999px; font-size: 11.5px; font-weight: 600; color: var(--ink);
    border: 1px solid transparent;

    &:hover { background: var(--hairline); }
    &.is-empty { border: 1px dashed var(--border2); color: var(--soft); font-weight: 500; }
  }
  .call-assign-name { max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* The two non-client choices, set apart from the roster above them. */
  .call-assign-plain { color: var(--soft); border-top: 1px solid var(--hairline); border-radius: 0; }

  /* ── One call ── */
  .call-detail { max-width: 760px; margin: 16px 0 0; display: flex; flex-direction: column; gap: 14px; }
  .call-card {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); padding: 16px 18px;
  }
  .call-card .section-label { margin-bottom: 9px; }
  /* pre-wrap: Fathom's summary is headings and bullets, and its line breaks are the only
     thing separating them once the markdown syntax is stripped. */
  .call-summary { margin: 0; font-size: 13px; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
  .call-empty { margin: 0; font-size: 12.5px; color: var(--dim); }

  .call-people { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
  .call-people li { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; flex-wrap: wrap; }
  .call-person-name { font-weight: 600; }
  .call-person-email { color: var(--soft); font-size: 11.5px; }
  .call-person-us {
    font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--soft); background: var(--inset); border-radius: 4px; padding: 1px 5px;
  }

  .call-outcomes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
  .call-outcome-title { font-size: 13px; font-weight: 600; display: block; }
  .call-outcome-title:hover { text-decoration: underline; }
  .call-outcome-meta { font-size: 11.5px; color: var(--soft); overflow-wrap: anywhere; }

  /* ⚠ Collapsed by default, and deliberately NOT a fixed-height scroll region: a nested
     scroll box inside a page that already scrolls is the phantom-scroll trap, and this
     needs no JS to open. Transcripts run to thousands of words and would otherwise bury
     "what came out of this call" above it. */
  .call-transcript {
    background: var(--card); border: 1px solid var(--border2); border-radius: var(--r-card);
    box-shadow: var(--shadow-sm); padding: 16px 18px;

    & > summary {
      list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: 10px;
      &::-webkit-details-marker { display: none; }
    }
    &[open] > summary { margin-bottom: 12px; }
  }
  .call-transcript-size { font-size: 11.5px; color: var(--dim); }
  /* pre-wrap, not <pre>: speaker lines are prose that should wrap at the card's width. */
  .call-transcript-body { font-size: 12.5px; line-height: 1.7; white-space: pre-wrap; overflow-wrap: anywhere; }
}

@media (max-width: 700px) {
  @layer components {
    /* The table reflows to cards here the way .campaigns-table already does; the two
       columns that carry the least on a phone go first. */
    .calls-table th:nth-child(4), .calls-table td:nth-child(4),
    .calls-table th:nth-child(5), .calls-table td:nth-child(5) { display: none; }
    .call-assign-name { max-width: 130px; }
  }
}
