
html {
    scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

#my-services-filter{
    display: none;
}

.grid-sizer,
.grid-project {
    /*width: 33.33%;*/
    /*padding: 5px;*/
}
@media screen and (max-width: 414px){
    .grid-project {
        /*width: 100%;*/
        /*padding: 5px;*/
    }
    #my-services-filter{
        display: block;
    }
    #services{
        display: none;
    }
}

/*.grid-project{*/
/*    float: left;*/
/*    &:hover{*/
/*         cursor:pointer;*/
/*    }*/
/*}*/
.grid-project .card{
    display: block;
    max-width: 100%;
    border: 10px solid white;
}
@media screen and (max-width: 414px){
    .grid-project .card {
        border: 5px solid white;
    }
}

.grid-project.grid-project__expanded {
    width: 66.66%;
    z-index: 2;
}

/* ── Sidebar: always keep the Services submenu expanded ── */
.pcoded-navbar .pcoded-hasmenu.pcoded-trigger > .pcoded-submenu {
    display: block !important;
    height: auto !important;
    overflow: visible !important;
}

/* ============================================================================
   My-Account → Services detail pages
   ----------------------------------------------------------------------------
   Extracted 2026-06-03 from per-template inline <style> blocks that were
   duplicated (and had begun to drift) across the report service views:
   plagiarism-check, ai-report, drillbit-report, ithenticate-report.
   Superset of every service's component styles — a few rules apply to only one
   service (e.g. .re-price-hero* = Drillbit's flat-fee card, .re-mk-ai = AI
   Report) but cost nothing on pages that don't use them. All selectors are
   scoped to the .re- and #re- prefixes, so they're inert on other dashboard pages.
   Source design hand-off: claude.ai/design bundle 2026-06-02.
   ============================================================================ */

@keyframes svcFadeSlideIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.svc-fade-slide-in { animation: svcFadeSlideIn .4s ease-out both; }

/* Trust strip */
.re-trust-strip { display: flex; flex-wrap: wrap; }
.re-trust-item  { display: flex; align-items: center; gap: 11px; flex: 1; min-width: 210px; padding: 14px 20px; }
.re-trust-item + .re-trust-item { border-left: 1px solid #eef0f3; }
.re-trust-item .ico { width: 34px; height: 34px; border-radius: 8px; background: var(--re-dash-success-soft); color: var(--re-dash-success); display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 18px; }
.re-trust-item .lbl { font-weight: 700; font-size: 13px; color: var(--re-dash-fg); line-height: 1.2; }
.re-trust-item .sub { font-size: 11px; color: var(--re-dash-fg-muted); }
@media (max-width: 767px) { .re-trust-item + .re-trust-item { border-left: none; border-top: 1px solid #eef0f3; } }

/* Novice primer icon tiles */
.re-primer-ico { width: 42px; height: 42px; border-radius: 8px; background: var(--re-dash-success-soft); color: var(--re-dash-success); display: flex; align-items: center; justify-content: center; margin-bottom: 12px; font-size: 20px; }

/* "What you're paying for" band */
.re-pay-band { display: flex; align-items: flex-start; padding: 8px; margin-bottom: 12px; background: var(--re-dash-success-soft); border-radius: 4px; font-size: 12px; color: #0a6f17; }
.re-pay-band i { margin-right: 8px; font-size: 16px; margin-top: 1px; }

/* ── Report preview panel ── */
.re-rp { display: flex; flex-wrap: wrap; gap: 24px; align-items: stretch; }
.re-rp-summary { flex: 0 0 230px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.re-donut { width: 150px; height: 150px; border-radius: 50%; background: conic-gradient(var(--arc,#1de9b6) 0 calc(var(--pct,8) * 3.6deg), #e9eef4 0); display: flex; align-items: center; justify-content: center; }
.re-donut-hole { width: 108px; height: 108px; border-radius: 50%; background: var(--re-dash-bg); display: flex; flex-direction: column; align-items: center; justify-content: center; }
.re-donut-val { font-family: 'Quicksand',sans-serif; font-weight: 700; font-size: 34px; color: var(--re-dash-fg); line-height: 1; white-space: nowrap; }
.re-donut-cap { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--re-dash-fg-muted); margin-top: 10px; font-weight: 700; }
.re-rp-sources { width: 100%; margin-top: 18px; text-align: left; }
.re-rp-srctitle { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--re-dash-fg-muted); margin-bottom: 8px; }
.re-src { display: flex; align-items: center; font-size: 12px; color: var(--re-dash-fg-secondary); margin-bottom: 6px; }
.re-src .dot { width: 10px; height: 10px; border-radius: 2px; margin-right: 8px; flex-shrink: 0; }
.re-src .pct { margin-left: auto; font-weight: 700; color: var(--re-dash-fg); }
.re-rp-doc { flex: 1; min-width: 280px; border: 1px solid #e4ebf2; border-radius: 6px; overflow: hidden; }
.re-rp-docbar { display: flex; align-items: center; gap: 6px; padding: 8px 12px; background: #f4f7fa; border-bottom: 1px solid #e4ebf2; }
.re-rp-dot { width: 9px; height: 9px; border-radius: 50%; background: #cfd8e3; }
.re-rp-docname { font-size: 11px; color: var(--re-dash-fg-muted); margin-left: 8px; }
.re-rp-page { padding: 18px 20px; font-size: 12.5px; line-height: 1.85; color: #3a4658; }
.re-rp-h { font-weight: 700; color: var(--re-dash-fg); margin-bottom: 6px; }
.re-rp-actions { float: right; display: flex; align-items: center; gap: 10px; }
.re-rp-expand { font-size: 11px; font-weight: 700; color: #00bcd4; text-decoration: none; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.re-rp-expand:hover { text-decoration: underline; }

/* Match highlights */
.re-mk { border-radius: 2px; padding: 0 2px; }
.re-mk1 { background: rgba(64,153,255,.20); }
.re-mk2 { background: rgba(16,192,24,.18); }
.re-mk3 { background: rgba(255,186,0,.22); }
.re-mk-ai { background: rgb(0 255 210 / 22%); }
.re-mk sup { font-weight: 700; font-size: 9px; }
.re-mk1 sup { color: #2b6fc2; }
.re-mk2 sup { color: #0a8f1a; }
.re-mk3 sup { color: #b97d00; }

/* Score acceptability bar */
.re-scale { margin-top: 14px; }
.re-scale-bar { height: 10px; border-radius: 999px; display: flex; overflow: hidden; }
.re-scale-bar span { display: block; height: 100%; }
.re-scale-ends { display: flex; justify-content: space-between; font-size: 10px; color: var(--re-dash-fg-muted); margin-top: 4px; }
.re-scale-note { font-size: 12px; color: var(--re-dash-fg-secondary); margin-top: 8px; }
.re-scale-note strong { color: var(--re-dash-brand-dark); }

/* Pricing table — flat compact 4-column list */
.re-slab-table-wrap { border:1px solid #e2e6ea; border-radius:8px; overflow:hidden; }
.re-price-table { width:100%; border-collapse:collapse; }
.re-price-table tbody tr td { border-bottom:0.5px solid #e9ecef; padding:11px 14px; vertical-align:middle; }
.re-price-table tbody tr:last-child td { border-bottom:none; }
.re-price-table .re-foot td { padding:9px 14px; font-size:11px; color:#b0bac8; border-top:0.5px solid #e9ecef; border-bottom:none !important; background:#fafbfc; }
.re-slab-score-cell { width:120px; }
.re-slab-band { font-family:'Quicksand',sans-serif; font-weight:700; font-size:14px; color:var(--re-dash-fg); display:block; line-height:1.2; }
.re-slab-desc { font-size:13px; color:var(--re-dash-fg-secondary); }
.re-slab-tat-cell { width:90px; font-size:12.5px; color:#8897ae; white-space:nowrap; }
.re-slab-price-cell { width:90px; text-align:right; white-space:nowrap; }
.re-slab-rate { font-family:'Quicksand',sans-serif; font-weight:700; font-size:17px; color:var(--re-dash-fg); }
.re-slab-unit { font-size:11px; color:var(--re-dash-fg-muted); font-weight:400; }
#re-quote { font-size: 13px; color: var(--re-dash-fg); margin-top: 6px; }
#re-quote .re-quote-tat { color: var(--re-dash-fg-muted); font-weight: 400; }

/* Flat-fee pricing hero card (Drillbit) */
.re-price-hero { padding: 4px 0 8px; }
.re-price-hero-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.re-price-hero-lbl { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--re-dash-fg-muted); }
.re-price-hero-badge { display: inline-flex; align-items: center; background: #fff3cd; color: #8a5700; font-size: 11px; font-weight: 700; padding: 3px 9px; border-radius: 999px; letter-spacing: .02em; }
.re-price-hero-was { font-size: 16px; color: #b0bac9; text-decoration: line-through; line-height: 1; margin-bottom: 4px; }
.re-price-hero-price { font-family: 'Quicksand', sans-serif; font-weight: 700; font-size: 52px; color: var(--re-dash-success); line-height: 1; letter-spacing: -.5px; }
.re-price-hero-usd { font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 8px; }
.re-price-hero-divider { border: none; border-top: 1px solid #eef0f3; margin: 18px 0 14px; }
.re-price-hero-includes { list-style: none; padding: 0; margin: 0; }
.re-price-hero-includes li { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #3a4658; padding: 5px 0; }
.re-price-hero-includes li i { color: var(--re-dash-success); font-size: 15px; flex-shrink: 0; }

/* Live delivery ticker */
.re-ticker { display: flex; align-items: center; gap: 12px; background: var(--re-dash-bg); border-radius: 4px; padding: 10px 16px; font-size: 12.5px; color: var(--re-dash-fg-secondary); box-shadow: 0 1px 3px rgba(43,52,69,.1), 0 1px 2px rgba(43,52,69,.05); }
.re-ticker-live { display: inline-flex; align-items: center; gap: 6px; font-weight: 700; color: var(--re-dash-brand-dark); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; flex-shrink: 0; }
.re-ticker-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--re-dash-success); }
@media (prefers-reduced-motion: no-preference) { .re-ticker-dot { animation: rePulse 1.8s infinite; } }
@keyframes rePulse { 0% { box-shadow: 0 0 0 0 rgba(16,192,24,.45); } 70% { box-shadow: 0 0 0 7px rgba(16,192,24,0); } 100% { box-shadow: 0 0 0 0 rgba(16,192,24,0); } }
.re-ticker-text { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.re-ticker-text b { color: var(--re-dash-fg); font-weight: 700; }

/* Sticky quote / CTA bar */
.re-sticky { position: fixed; left: 250px; right: 0; bottom: 0; z-index: 1050; background: var(--re-dash-bg); border-top: 1px solid #e4ebf2; box-shadow: 0 -4px 16px rgba(43,52,69,.08); transform: translateY(115%); transition: transform .25s ease; }
.re-sticky.is-visible { transform: none; }
.re-sticky-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 11px 24px; }
.re-sticky-quote { font-size: 13.5px; color: var(--re-dash-fg); }
.re-sticky-quote .re-quote-tat { color: var(--re-dash-fg-muted); }
.re-sticky-btn { background: var(--re-dash-success); color: var(--re-dash-bg); font-weight: 700; padding: 9px 22px; border-radius: 6px; text-decoration: none; font-size: 13.5px; white-space: nowrap; }
.re-sticky-btn:hover { filter: brightness(.95); color: var(--re-dash-bg); }
/* Bootstrap adds body.modal-open while the sample modal is open — keep the
   sticky bar out of the way so it doesn't float over the modal backdrop. */
body.modal-open .re-sticky { display: none; }

/* Show / hide matches toggle */
.re-hl-toggle { float: right; background: #f1f3f6; border: none; border-radius: 999px; font-size: 11px; font-weight: 700; color: var(--re-dash-fg-secondary); padding: 5px 13px; cursor: pointer; }
.re-hl-toggle:hover { background: #e4e8ee; color: var(--re-dash-fg); }
.re-rp.re-nohl .re-mk { background: transparent; border-bottom: none; }
.re-rp.re-nohl .re-mk sup { display: none; }

/* Sample report modal — native Bootstrap 4 modal (.modal/.modal-dialog/.modal-content
   handle show/hide/backdrop/esc) wearing the design's chrome. */
.re-sample-modal .modal-dialog { max-width: 760px; }
.re-sample-modal .modal-content { border: none; border-radius: 8px; overflow: hidden; box-shadow: 0 20px 60px rgba(15,22,33,.3); }
.re-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid #eef0f3; }
.re-modal-head h5 { margin: 0; font-family: 'Quicksand',sans-serif; font-weight: 700; font-size: 15px; color: var(--re-dash-fg); }
.re-modal-x { background: none; border: none; color: var(--re-dash-fg-muted); cursor: pointer; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; opacity: 1; }
.re-modal-x:hover { background: #f1f3f6; color: var(--re-dash-fg); }
.re-modal-body { padding: 18px; }
.re-modal-foot { padding: 12px 18px; border-top: 1px solid #eef0f3; font-size: 12px; color: var(--re-dash-fg-muted); background: #fafbfc; }

/* ============================================================================
   Non-report service pages (Proofreading, Grammar, Citation, Document
   Formatting, Data Analysis, Plagiarism Removal, AI Reduction).
   Shared component set + per-service glue lifted from the Claude Design
   hand-off (research-experts-dashboard-design). No new tokens/fonts/colors —
   reuses the existing brand palette. .re-ticker*, .re-row-active and
   .re-price-table already live above, so they are NOT redefined here.
   ============================================================================ */

/* Service page-title strip */
.re-page-title{display:flex;align-items:center;gap:14px;}
.re-page-title .re-svc-icon{width:40px;height:40px;border-radius:8px;background:var(--re-dash-success);color:var(--re-dash-bg);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:20px;}
.re-page-title .re-bc{font-size:12px;color:var(--re-dash-fg-muted);}
.re-page-title .re-bc a{color:var(--re-dash-fg-secondary);text-decoration:none;}
.re-page-title .re-bc .active{color:var(--re-dash-success);}

/* Entrance animation (resting state visible; animation plays from hidden) */
@keyframes fadeSlideIn{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}
.fade-slide-in{animation:fadeSlideIn .4s ease-out;}
@media (prefers-reduced-motion: reduce){ .fade-slide-in{animation:none;} }

/* Navy promise band */
.re-band-navy{background:linear-gradient(135deg,#0e2462 0%,#1e3a8a 60%,#1d4ed8 100%);border-radius:10px;color:var(--re-dash-bg);padding:38px 36px;position:relative;overflow:hidden;}
.re-band-navy .re-eyebrow{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.12em;color:#8fb6ff;}
.re-band-navy h2{font-family:'Quicksand',sans-serif;font-weight:700;color:var(--re-dash-bg);font-size:32px;line-height:1.16;margin:10px 0 0;max-width:700px;}
.re-band-navy h2 em{font-style:normal;color:#7ff0a6;}
.re-band-navy p{color:rgba(255,255,255,.82);font-size:14px;max-width:620px;margin-top:12px;}
.re-band-cta{display:inline-block;background:var(--re-dash-success);color:var(--re-dash-bg);font-weight:700;padding:11px 26px;border-radius:6px;text-decoration:none;font-size:14px;margin-top:20px;}
.re-band-cta:hover{filter:brightness(.95);color:var(--re-dash-bg);}
.re-stat-row{display:flex;flex-wrap:wrap;gap:0;margin-top:30px;border-top:1px solid rgba(255,255,255,.15);padding-top:24px;}
.re-stat{flex:1;min-width:140px;padding:2px 22px 2px 0;}
.re-stat .n{font-family:'Quicksand',sans-serif;font-weight:700;font-size:30px;line-height:1;}
.re-stat .l{font-size:12px;color:rgba(255,255,255,.7);margin-top:7px;line-height:1.3;}

/* Before / after compare blocks */
.re-ba{display:flex;flex-wrap:wrap;gap:18px;align-items:stretch;}
.re-ba-side{flex:1;min-width:240px;border:1px solid #eef0f3;border-radius:6px;padding:18px;}
.re-ba-side.is-before{background:#fff5f6;border-color:#ffd9df;}
.re-ba-side.is-after{background:#eef9ec;border-color:#cdeec6;}
.re-ba-tag{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;margin-bottom:8px;}
.re-ba-side.is-before .re-ba-tag{color:#ff5370;}
.re-ba-side.is-after .re-ba-tag{color:var(--re-dash-brand-dark);}
.re-ba-score{font-family:'Quicksand',sans-serif;font-weight:700;font-size:34px;line-height:1;}
.re-ba-side.is-before .re-ba-score{color:#ff5370;}
.re-ba-side.is-after .re-ba-score{color:var(--re-dash-brand-dark);}
.re-ba-score .u{font-size:18px;}
.re-ba-cap{font-size:12px;color:var(--re-dash-fg-muted);margin-top:4px;}
.re-ba-snip{font-size:12px;line-height:1.65;color:var(--re-dash-fg-secondary);margin-top:14px;padding-top:12px;border-top:1px dashed #e4ebf2;}
.re-hl-red{background:rgba(255,83,112,.18);color:#c0314a;border-radius:2px;padding:0 2px;}
.re-del{color:#ff5370;text-decoration:line-through;}
.re-ins{color:var(--re-dash-brand-dark);text-decoration:underline;text-decoration-color:#9bd592;}
.re-arrow-mid{display:flex;align-items:center;justify-content:center;color:var(--re-dash-success);flex:0 0 36px;}
@media (max-width:767px){.re-arrow-mid{transform:rotate(90deg);height:28px;}}

/* Process stepper */
.re-proc-row{display:flex;align-items:flex-start;flex-wrap:wrap;gap:0;}
.re-proc-step{flex:1;min-width:180px;}
.re-proc-num{width:38px;height:38px;border-radius:50%;background:var(--re-dash-success);color:var(--re-dash-bg);display:flex;align-items:center;justify-content:center;font-family:'Quicksand',sans-serif;font-weight:700;font-size:16px;margin-bottom:12px;}

/* Scope include / exclude */
.re-scope-item{display:flex;align-items:flex-start;gap:10px;font-size:13px;color:var(--re-dash-fg);margin-bottom:11px;}
.re-scope-item:last-child{margin-bottom:0;}
.re-scope-item .ic{width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:12px;margin-top:1px;}
.re-scope-item.yes .ic{background:var(--re-dash-success-soft);color:var(--re-dash-brand-dark);}
.re-scope-item.no .ic{background:#fdeaed;color:#ff5370;}

/* Cost estimator (shared) */
.re-est-cap{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--re-dash-fg-muted);margin-bottom:8px;display:flex;align-items:baseline;justify-content:space-between;}
.re-est-cap .v{font-family:'Quicksand',sans-serif;font-weight:700;font-size:24px;color:var(--re-dash-fg);letter-spacing:0;}
.re-step{display:inline-flex;align-items:center;border:1px solid #e0e3e7;border-radius:6px;overflow:hidden;}
.re-step button{width:42px;height:44px;border:none;background:#f4f7fa;color:var(--re-dash-fg);font-size:20px;line-height:1;cursor:pointer;}
.re-step button:hover{background:#e9eef4;}
.re-step input{width:76px;height:44px;border:none;text-align:center;font-size:17px;font-weight:700;color:var(--re-dash-fg);font-family:'Quicksand',sans-serif;}
.re-step input:focus{outline:none;}
.re-est-hint{font-size:12px;color:var(--re-dash-fg-muted);margin-top:9px;}
.re-est-cta{display:block;text-align:center;background:var(--re-dash-success);color:var(--re-dash-bg);font-weight:700;padding:13px;border-radius:6px;text-decoration:none;font-size:15px;}
.re-est-cta:hover{filter:brightness(.95);color:var(--re-dash-bg);}
.re-slabquote{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:16px;background:#2b3445;color:var(--re-dash-bg);border-radius:8px;padding:18px 22px;}
.re-slabquote .big{font-family:'Quicksand',sans-serif;font-weight:700;font-size:30px;line-height:1;}
.re-slabquote .sub{font-size:12px;color:#9aa6bd;margin-top:4px;}
.re-slabquote .re-est-cta{padding:11px 24px;white-space:nowrap;}

/* Clickable slab table hover / active / common-tag */
.re-price-table.re-clickable tbody tr { cursor:pointer; }
.re-price-table.re-clickable tbody tr:hover td { background:#f7faff; }
.re-price-table tbody tr.re-row-active td { background:#f3fcf4; }
.re-price-table tbody tr.re-row-active td:first-child { box-shadow:inset 3px 0 0 var(--re-dash-success); }
.re-price-table tbody tr.re-row-active td { background:#f3fcf4 !important; }
.re-tag-common { display:inline-block; font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; background:#e6f9f0; color:#0a8f4f; border-radius:4px; padding:2px 6px; margin-top:5px; }

/* Dual promise strip */
.re-promise{display:flex;flex-wrap:wrap;}
.re-promise-item{flex:1;min-width:240px;display:flex;align-items:flex-start;gap:13px;padding:18px 22px;}
.re-promise-item+.re-promise-item{border-left:1px solid #eef0f3;}
.re-promise-item .ic{width:42px;height:42px;border-radius:50%;background:var(--re-dash-success-soft);color:var(--re-dash-brand-dark);display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:20px;}
.re-promise-item .t{font-family:'Quicksand',sans-serif;font-weight:700;font-size:15px;color:var(--re-dash-fg);}
.re-promise-item .s{font-size:12.5px;color:var(--re-dash-fg-secondary);margin-top:3px;line-height:1.45;}
@media (max-width:767px){.re-promise-item+.re-promise-item{border-left:none;border-top:1px solid #eef0f3;}}

/* Testimonial cards */
.re-quote-stars{color:#ffba00;font-size:13px;letter-spacing:3px;margin-bottom:9px;}
.re-quote-card p{font-size:13px;color:#3a4658;line-height:1.62;margin:0;}
.re-quote-who{font-size:12px;color:var(--re-dash-fg-muted);margin-top:13px;}
.re-quote-who b{color:var(--re-dash-fg);display:block;font-size:13px;font-family:'Quicksand',sans-serif;}

/* FAQ accordion (native <details>) */
.re-faq details{border:1px solid #eef0f3;border-radius:6px;margin-bottom:10px;overflow:hidden;}
.re-faq summary{list-style:none;cursor:pointer;padding:14px 16px;font-weight:600;font-size:13.5px;color:var(--re-dash-fg);display:flex;justify-content:space-between;align-items:center;gap:12px;}
.re-faq summary::-webkit-details-marker{display:none;}
.re-faq summary .pm{font-size:18px;color:var(--re-dash-success);font-weight:700;flex-shrink:0;}
.re-faq details[open] summary{background:#f4f7fa;}
.re-faq .a{padding:2px 16px 15px;font-size:13px;color:var(--re-dash-fg-secondary);line-height:1.66;}

/* ---- Proofreading (.pf-*) ---- */
.pf-track{font-size:13.5px;line-height:2.15;color:var(--re-dash-fg);}
.pf-track del{color:#ff5370;text-decoration:line-through;text-decoration-thickness:1.5px;margin-right:1px;}
.pf-track ins{color:var(--re-dash-brand-dark);text-decoration:underline;text-decoration-color:#9bd592;text-decoration-thickness:1.5px;margin-left:1px;}
.pf-track .pf-note{display:inline-block;white-space:nowrap;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--re-dash-fg-muted);border:1px solid #e4ebf2;border-radius:3px;padding:0 4px;vertical-align:super;margin-left:2px;}
.pf-margin{border-left:3px solid var(--re-dash-success);background:#f4faf2;border-radius:0 6px 6px 0;padding:10px 14px;font-size:12px;color:#3a4658;line-height:1.6;}
.pf-margin b{color:var(--re-dash-brand-dark);}
.pf-pass-num{width:30px;height:30px;border-radius:50%;background:var(--re-dash-success-soft);color:var(--re-dash-brand-dark);display:flex;align-items:center;justify-content:center;font-family:'Quicksand',sans-serif;font-weight:700;font-size:14px;flex-shrink:0;}

/* ---- Grammar Correction (.gc-*) ---- */
.gc-err{height:100%;}
.gc-err .card-block{padding:18px 18px 16px;}
.gc-err .gc-cat{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--re-dash-brand-dark);background:var(--re-dash-success-soft);border-radius:999px;padding:3px 10px;margin-bottom:11px;}
.gc-err h6{font-family:'Quicksand',sans-serif;font-weight:700;font-size:14px;color:var(--re-dash-fg);margin-bottom:9px;}
.gc-ex{font-size:12.5px;line-height:1.5;}
.gc-ex .l{display:flex;gap:7px;align-items:baseline;}
.gc-ex .l+.l{margin-top:5px;}
.gc-ex .tag{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0;width:42px;}
.gc-ex .tag.bad{color:#ff5370;}
.gc-ex .tag.good{color:var(--re-dash-brand-dark);}
.gc-ex .bad-t{color:var(--re-dash-fg-muted);text-decoration:line-through;text-decoration-color:#ffb3c0;}
.gc-ex .good-t{color:var(--re-dash-fg);}
.gc-ex .good-t b{color:var(--re-dash-brand-dark);font-weight:700;}
.gc-pick{width:100%;border-collapse:separate;border-spacing:0;}
.gc-pick th,.gc-pick td{padding:13px 16px;font-size:13px;text-align:left;vertical-align:top;border-bottom:1px solid #eef0f3;}
.gc-pick thead th{background:#f4f7fa;font-family:'Quicksand',sans-serif;font-weight:700;font-size:13.5px;color:var(--re-dash-fg);border-bottom:2px solid #e4ebf2;}
.gc-pick thead th:first-child{background:transparent;}
.gc-pick tbody th{font-weight:600;color:var(--re-dash-fg-secondary);font-size:12.5px;width:30%;}
.gc-pick .gc-this{background:#f4faf2;}
.gc-pick .gc-this-h{color:var(--re-dash-brand-dark)!important;}
.gc-pick .yes{color:var(--re-dash-brand-dark);font-weight:700;}
.gc-pick .no{color:#c3ccd9;}
.gc-pick .part{color:var(--re-dash-fg-muted);}
.gc-pick td a{color:var(--re-dash-brand-dark);font-weight:600;}
.gc-pick tfoot td{font-size:11.5px;color:var(--re-dash-fg-muted);border-bottom:none;padding-top:12px;}
@media (max-width:767px){.gc-pick{font-size:12px;} .gc-pick th,.gc-pick td{padding:9px 8px;}}

/* ---- Citation Formatting (.cf-*) ---- */
.cf-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:18px;}
.cf-tab{border:1.5px solid #e4ebf2;background:var(--re-dash-bg);border-radius:999px;padding:7px 16px;font-size:12.5px;font-weight:700;color:var(--re-dash-fg-secondary);cursor:pointer;font-family:'Open Sans',sans-serif;}
.cf-tab:hover{border-color:#bfe0b6;color:var(--re-dash-fg);}
.cf-tab.is-on{background:var(--re-dash-success);border-color:var(--re-dash-success);color:var(--re-dash-bg);}
.cf-ref{border:1px solid #eef0f3;border-radius:6px;padding:14px 16px;margin-bottom:12px;background:#fbfdfb;}
.cf-ref:last-child{margin-bottom:0;}
.cf-ref-type{display:inline-block;white-space:nowrap;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--re-dash-fg-muted);background:#eef4fb;border-radius:3px;padding:2px 8px;margin-bottom:9px;}
.cf-ref-body{font-size:13px;line-height:1.7;color:var(--re-dash-fg);}
.cf-ref-body i{color:var(--re-dash-fg);}
.cf-ref-body .hl{background:rgba(16,192,24,.14);border-radius:2px;padding:0 2px;}
.cf-note{display:flex;align-items:flex-start;gap:9px;background:#eef4fb;border-radius:6px;padding:11px 14px;font-size:12.5px;color:#2b4a73;margin-top:4px;line-height:1.55;}
.cf-note b{color:var(--re-dash-fg);}
.cf-styles{display:flex;flex-wrap:wrap;gap:10px;}
.cf-style-chip{flex:1;min-width:130px;border:1px solid #eef0f3;border-radius:8px;padding:13px 15px;}
.cf-style-chip .n{font-family:'Quicksand',sans-serif;font-weight:700;font-size:14px;color:var(--re-dash-fg);}
.cf-style-chip .d{font-size:11.5px;color:var(--re-dash-fg-muted);margin-top:3px;line-height:1.4;}

/* ---- Document Formatting (.df-*) ---- */
.df-compare{display:flex;flex-wrap:wrap;gap:20px;align-items:stretch;}
.df-col{flex:1;min-width:200px;}
.df-col-tag{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;margin-bottom:9px;display:flex;align-items:center;gap:7px;}
.df-col.before .df-col-tag{color:#ff5370;}
.df-col.after .df-col-tag{color:var(--re-dash-brand-dark);}
.df-page{background:var(--re-dash-bg);border:1px solid #e4ebf2;border-radius:3px;box-shadow:0 1px 3px rgba(43,52,69,.1),0 6px 18px rgba(43,52,69,.06);aspect-ratio:1/1.3;max-width:230px;margin:0 auto;padding:14% 13%;position:relative;overflow:hidden;}
.df-col.before .df-page{padding:9% 8% 9% 16%;}
.df-line{height:5px;border-radius:2px;background:#dde3ec;margin-bottom:7px;}
.df-line.sh{background:#e9edf3;}
.df-h{height:8px;border-radius:2px;background:var(--re-dash-success);margin:14px 0 9px;width:52%;}
.df-h.num{position:relative;}
.df-gap{height:11px;}
.df-pageno{position:absolute;bottom:6%;left:0;right:0;text-align:center;font-size:8px;color:#b3bccb;}
.df-col.before .df-pageno{display:none;}
.df-title{height:10px;width:64%;background:#2b3445;border-radius:2px;margin:0 auto 8px;}
.df-title-sub{height:5px;width:40%;background:#cfd6e0;border-radius:2px;margin:0 auto 6px;}
.df-toc-row{display:flex;align-items:center;gap:6px;margin-bottom:8px;}
.df-toc-row .t{height:5px;border-radius:2px;background:#dde3ec;flex:0 0 auto;}
.df-toc-row .dots{flex:1;border-bottom:1.5px dotted #cfd6e0;height:1px;margin-bottom:2px;}
.df-toc-row .pg{width:7px;height:5px;border-radius:1px;background:#bcc5d3;}
.df-badge{position:absolute;top:7%;right:-1px;background:var(--re-dash-success);color:var(--re-dash-bg);font-size:8.5px;font-weight:700;padding:3px 9px;border-radius:3px 0 0 3px;letter-spacing:.03em;}
.df-skew{transform:rotate(-1.2deg);}
.df-tpl{display:flex;flex-wrap:wrap;gap:9px;}
.df-tpl-chip{border:1.5px solid #e4ebf2;background:var(--re-dash-bg);border-radius:999px;padding:8px 17px;font-size:12.5px;font-weight:700;color:var(--re-dash-fg-secondary);cursor:pointer;font-family:'Open Sans',sans-serif;}
.df-tpl-chip:hover{border-color:#bfe0b6;color:var(--re-dash-fg);}
.df-tpl-chip.is-on{background:var(--re-dash-success);border-color:var(--re-dash-success);color:var(--re-dash-bg);}
.df-tpl-note{font-size:12.5px;color:var(--re-dash-fg-secondary);line-height:1.6;margin-top:14px;background:#f4faf2;border-radius:6px;padding:12px 15px;}
.df-tpl-note b{color:var(--re-dash-brand-dark);}
.df-incl{display:flex;align-items:flex-start;gap:11px;border:1.5px solid #e4ebf2;border-radius:8px;padding:12px 14px;margin-bottom:9px;}
.df-check{width:20px;height:20px;border-radius:5px;border:2px solid var(--re-dash-success);background:var(--re-dash-success);flex-shrink:0;margin-top:1px;display:flex;align-items:center;justify-content:center;color:var(--re-dash-bg);}
.df-incl .df-a-t{font-weight:700;font-size:13px;color:var(--re-dash-fg);}
.df-incl .df-a-s{font-size:11.5px;color:var(--re-dash-fg-muted);margin-top:1px;line-height:1.4;}
.df-incl .df-a-p{margin-left:auto;font-family:'Quicksand',sans-serif;font-weight:700;font-size:13px;color:var(--re-dash-brand-dark);white-space:nowrap;}

/* ---- Data Analysis (.da-*) — navy+teal identity, scoped to this page ---- */
.da-page .re-svc-icon{background:linear-gradient(135deg,#0e2462,#1d7d8c);}
.da-page .re-band-navy h2 em{color:#1de9b6;}
.da-page .re-band-cta{background:#1de9b6;color:#06343a;}
.da-page .re-band-cta:hover{filter:brightness(.95);color:#06343a;}
.da-page .re-bc .active{color:#0fb39a;}
.da-page .re-est-cta{background:#1de9b6;color:#06343a;}
.da-page .re-est-cta:hover{color:#06343a;}
.da-page .re-promise-item .ic,.da-page .re-scope-item.yes .ic{background:#e4fbf5;color:#0fae93;}
.da-page .re-proc-num{background:#0fae93;}
.da-eyebrow-teal{color:#1de9b6;}
.da-an{height:100%;}
.da-an .ico{width:42px;height:42px;border-radius:9px;background:#e4fbf5;color:#0fae93;display:flex;align-items:center;justify-content:center;font-size:20px;margin-bottom:12px;}
.da-an h6{font-family:'Quicksand',sans-serif;font-weight:700;font-size:14px;color:var(--re-dash-fg);margin-bottom:7px;}
.da-an p{font-size:12.5px;color:var(--re-dash-fg-secondary);line-height:1.55;margin:0;}
.da-tools{display:flex;flex-wrap:wrap;gap:10px;align-items:center;}
.da-tool{display:inline-flex;align-items:center;gap:8px;border:1px solid #d8e8e4;background:#f4fbf9;border-radius:8px;padding:9px 15px;font-weight:700;font-size:13px;color:var(--re-dash-fg);font-family:'Quicksand',sans-serif;}
.da-tool .dot{width:9px;height:9px;border-radius:50%;background:#0fae93;flex-shrink:0;}
.da-tier{border:1.5px solid #e4ebf2;border-radius:10px;padding:22px 22px 24px;height:100%;display:flex;flex-direction:column;background:var(--re-dash-bg);}
.da-tier.feat{border-color:#0fae93;box-shadow:0 6px 22px rgba(15,174,147,.13);position:relative;}
.da-tier.feat::before{content:"Most requested";position:absolute;top:-11px;left:22px;background:#0fae93;color:var(--re-dash-bg);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 11px;border-radius:999px;}
.da-tier .t{font-family:'Quicksand',sans-serif;font-weight:700;font-size:16px;color:var(--re-dash-fg);}
.da-tier .from{font-size:12px;color:var(--re-dash-fg-muted);margin-top:3px;}
.da-tier .price{font-family:'Quicksand',sans-serif;font-weight:700;font-size:30px;color:var(--re-dash-fg);margin:13px 0 2px;}
.da-tier .price small{font-family:'Open Sans',sans-serif;font-weight:400;font-size:12px;color:var(--re-dash-fg-muted);}
.da-tier ul{list-style:none;padding:0;margin:16px 0 0;font-size:12.5px;color:var(--re-dash-fg-secondary);}
.da-tier ul li{display:flex;gap:8px;align-items:flex-start;margin-bottom:9px;line-height:1.45;}
.da-tier ul li i{color:#0fae93;flex-shrink:0;margin-top:2px;}
.da-cb{background:linear-gradient(135deg,#0e2462 0%,#155e6b 100%);border-radius:10px;color:var(--re-dash-bg);padding:30px 32px;}
.da-cb .lbl{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:#1de9b6;}
.da-cb h3{font-family:'Quicksand',sans-serif;font-weight:700;font-size:22px;color:var(--re-dash-bg);margin:8px 0 0;}
.da-cb .da-phone{font-family:'Quicksand',sans-serif;font-weight:700;font-size:20px;color:#1de9b6;}

/* ===================== My Projects — converting list (.odr-projects) ===================== */
/* Colour tokens moved to :root in dashboard-cards.css (--re-dash-*). They were
   declared here, and again at two other places in this file, scoped to a hardcoded
   list of screens — which is why a screen not on the list got none of this. */
.pcoded-content .card.table-card{border:1px solid var(--re-dash-border);border-radius:12px;box-shadow:0 1px 2px rgba(16,38,48,.04),0 14px 34px -24px rgba(16,38,48,.22);}
.pcoded-content .card-header{border-bottom:1px solid #eef2f5;}
.pcoded-content .card-header h5{font-family:'Quicksand',sans-serif;font-weight:700;color:var(--re-dash-fg);margin:0;}
.pcoded-content #dt-ajax-data-tables{border-collapse:separate;border-spacing:0;}
.pcoded-content #dt-ajax-data-tables.table-striped tbody tr:nth-of-type(odd){background:transparent;}
.pcoded-content #dt-ajax-data-tables thead th{font-family:'Open Sans',sans-serif;text-transform:uppercase;font-size:10.5px;letter-spacing:.07em;color:var(--re-dash-fg-muted);font-weight:700;background:#fbfcfd;border-top:none;border-bottom:1px solid var(--re-dash-border);padding:12px 14px;vertical-align:middle;}
.pcoded-content #dt-ajax-data-tables tbody td{border-top:none;border-bottom:1px solid #eef2f5;padding:14px;vertical-align:middle;font-size:13px;color:var(--re-dash-fg-secondary);}
.pcoded-content #dt-ajax-data-tables tbody tr:hover{background:#f8fbf8;}
.pcoded-content #dt-ajax-data-tables tbody tr:last-child td{border-bottom:none;}
/* My Projects row identity block. Mirrors docs/user-view-rework/design/my-projects.html,
   which took it from ui-shell-and-pay-gate.html — the FILE is the headline and the id is
   secondary mono, so the list and the project page render the same block. */
.pcoded-content .idrow{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;}
.pcoded-content .idmain{min-width:0;flex:1 1 auto;}
.pcoded-content .idrow .mfee{display:none;}
.pcoded-content .idrow .pid{font-family:var(--re-dash-mono,ui-monospace,Menlo,monospace);font-size:13px;color:var(--re-dash-fg-secondary);display:inline-flex;align-items:center;gap:6px;}
.pcoded-content .idrow .pid a{color:inherit;text-decoration:none;}
.pcoded-content .idrow .pid a:hover{color:var(--re-dash-fg);text-decoration:underline;}
.pcoded-content .idrow .fname{font-family:'Quicksand',sans-serif;font-weight:700;font-size:15px;line-height:1.3;margin-top:3px;word-break:break-word;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.pcoded-content .idrow .fname.gone{color:var(--re-dash-fg-muted);}
.pcoded-content .idrow .fmeta{font-size:12px;color:var(--re-dash-fg-muted);margin-top:3px;}
/* The date leads the block rather than trailing it (owner, 2026-09-04). */
.pcoded-content .idrow .fmeta.lead{margin-top:0;margin-bottom:4px;}
.pcoded-content .copyic,.pcoded-content .copy-icon{color:var(--re-dash-fg-muted);font-size:12px;cursor:pointer;}
.pcoded-content .copy-icon{margin-left:8px;opacity:0;transition:opacity .2s;color:var(--re-dash-info);}
.pcoded-content .copy-container:hover .copy-icon{opacity:1;}
.pcoded-content .odr-gone{color:var(--re-dash-danger-dark);font-weight:600;}
/* AdminDek's global .btn sets text-transform:capitalize, which re-cased "Reduce both"
   into "Reduce Both". The labels are already sentence case; only the transform is wrong,
   and only here. Same fix .re-pd already carries for the project page. */
/* NOTE the compound selector, not a descendant one: the wrapper is
   <div class="pcoded-content odr-projects">, ONE element. `.pcoded-content .odr-projects`
   matches nothing, which is how the gradient and the capitalize survived a local pass and
   only showed on FEATURE. */
.pcoded-content.odr-projects .btn{text-transform:none;}
/* AdminDek paints .btn-success as a gradient at a later specificity than the flat rule at
   :534, so Add New Project came out turquoise. R11: no gradient buttons on this screen —
   the flat brand green, the same one the project-details views use. */
.pcoded-content.odr-projects .btn-success{background:var(--re-dash-success);background-image:none;border-color:var(--re-dash-success);color:var(--re-dash-fg-inverse);}
.pcoded-content.odr-projects .btn-success:hover{background:var(--re-dash-success-dark);background-image:none;border-color:var(--re-dash-success-dark);}
.pcoded-content .card-body{overflow-x:auto;}
.pcoded-content #dt-ajax-data-tables{min-width:880px;}
/* --- customer projects list chrome (scoped: `.odr-projects` is used by exactly one
   template, view-view-projects2.php, so none of this can reach an admin screen) --- */
/* Pagination and the row count were rendered TWICE, top and bottom. On a phone the page
   is ~4900px tall, so the top copy sat thousands of pixels from the rows it controlled.
   Keep the bottom pair; the top strip keeps only the page-length control. */
.pcoded-content.odr-projects .dt-top .dataTables_info,
.pcoded-content.odr-projects .dt-top .dataTables_paginate{display:none;}
/* "Show [10] entries" broke across three lines at every width — the select is a
   form-control (display:block) inside an inline-block label. */
.pcoded-content.odr-projects .dataTables_length label{display:flex;align-items:center;gap:8px;white-space:nowrap;margin-bottom:0;}
.pcoded-content.odr-projects .dataTables_length select{width:auto;min-width:76px;}

/* The row's next-step button, now inside the project cell. Sits under the file name so
   it can never be clipped by the table's right edge (see get_columns_titles()). */
.pcoded-content .idmain .btn-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;}
.pcoded-content .idmain .btn-row .btn{white-space:nowrap;}
/* Plag + AI in one cell; the chips wrap rather than widen the column. */
/* Scores stack; both are .chip, the same badge the status column uses. */
.pcoded-content .chipset{display:flex;flex-direction:column;gap:5px;align-items:flex-start;}
.pcoded-content .chip{display:inline-flex;align-items:center;font-size:13px;font-weight:600;line-height:1;padding:7px 11px;border-radius:999px;border:1px solid;white-space:nowrap;}
.pcoded-content .chip.sm{font-size:11.5px;padding:4px 8px;}
.pcoded-content .chip.sm .k{font-weight:500;opacity:.85;margin-right:3px;}
.pcoded-content .chip.done{color:var(--re-dash-success-darker);background:var(--re-dash-success-soft);border-color:var(--re-dash-success-line);}
.pcoded-content .chip.ready{color:var(--re-dash-warning-dark);background:var(--re-dash-warning-soft);border-color:var(--re-dash-warning-line);}
.pcoded-content .chip.ref{color:var(--re-dash-danger-dark);background:var(--re-dash-danger-soft);border-color:var(--re-dash-danger-line);}
.pcoded-content .chip.none{border-color:transparent;background:none;color:var(--re-dash-fg-muted);padding-left:0;}
/* `new` was the one badge modifier the design files define and this stylesheet had never
   picked up — every screen that wanted a neutral, informational badge had nothing to use. */
.pcoded-content .chip.new{color:var(--re-dash-info-dark);background:var(--re-dash-info-soft);border-color:var(--re-dash-info-line);}
.pcoded-content .odr-clone{display:inline-block;font-size:12px;margin-top:5px;color:var(--re-dash-info-dark);text-decoration:none;}
.pcoded-content .odr-clone:hover{text-decoration:underline;}
.pcoded-content tr.odr-row--pay td:first-child{box-shadow:inset 3px 0 0 #e08a00;}
.pcoded-content tr.odr-row--upsell td:first-child{box-shadow:inset 3px 0 0 var(--re-dash-success);}
/* ONE .odr-pill component, shared by every screen that renders a status/state
   chip: this file's own --delivered/--completed/--received/--rejected/--paused
   family below (project status, functions-html.php + class.projects_users.php,
   both build the modifier from a sanitized status slug) AND the --ok/--muted/
   --danger family further down (style.css ~992 — Users, My Leads, Offers,
   Transactions, sales-worklist). Two modifier vocabularies, ONE base rule —
   there used to be two competing `.odr-pill{}` declarations with different
   font-size/padding/text-transform, so which one "won" depended on file
   order, not intent. Consolidated 2026-08-07; do not re-add a second base
   declaration when adding a modifier — extend the vocabulary here instead. */
.pcoded-content .odr-pill{display:inline-flex;align-items:center;gap:5px;font-family:'Open Sans',sans-serif;font-weight:700;font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;line-height:1;padding:5px 9px;border-radius:999px;white-space:nowrap;}
.pcoded-content .odr-pill::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;}
.pcoded-content .odr-pill--delivered{color:var(--re-dash-success-dark);background:var(--re-dash-success-soft);}
.pcoded-content .odr-pill--completed, .pcoded-content .odr-pill--advance-awaited{color:var(--re-dash-warning);background:var(--re-dash-warning-soft);}
.pcoded-content .odr-pill--received, .pcoded-content .odr-pill--under-review, .pcoded-content .odr-pill--started, .pcoded-content .odr-pill--accepted{color:var(--re-dash-info);background:var(--re-dash-info-soft);}
.pcoded-content .odr-pill--rejected, .pcoded-content .odr-pill--refunded, .pcoded-content .odr-pill--suspended{color:var(--re-dash-danger);background:var(--re-dash-danger-soft);}
.pcoded-content .odr-pill--paused, .pcoded-content .odr-pill--reopened{color:var(--re-dash-fg-secondary);background:var(--re-dash-border-light);}
.pcoded-content .odr-chip{display:inline-flex;align-items:baseline;gap:1px;font-family:'Quicksand',sans-serif;font-weight:700;font-size:12.5px;padding:3px 8px;border-radius:7px;}
.pcoded-content .odr-chip--ok{color:var(--re-dash-success-dark);background:var(--re-dash-success-soft);}
.pcoded-content .odr-chip--warn{color:var(--re-dash-warning);background:var(--re-dash-warning-soft);}
.pcoded-content .odr-chip--danger{color:var(--re-dash-danger);background:var(--re-dash-danger-soft);}
.pcoded-content .odr-chip--none{color:var(--re-dash-fg-muted);}
.pcoded-content .odr-fee{font-family:var(--re-dash-mono,ui-monospace,Menlo,monospace);color:var(--re-dash-fg);white-space:nowrap;font-size:13px;}
/* The two figures were touching — "₹20 / ₹20" needs air around the slash. */
.pcoded-content .odr-slash{color:var(--re-dash-fg-muted);margin:0 6px;}
.pcoded-content .odr-paid{color:var(--re-dash-fg-secondary);}
.pcoded-content .odr-saved{display:block;font-size:11.5px;color:var(--re-dash-success-darker);margin-top:5px;}

/* ---------------------------------------------------------------
   Credits history row (.odr-credits)

   The amount is why the customer opened this screen; before this it was body
   text with no size and no alignment, and the balance was a bare number in
   square brackets. Money is the anchor now, signed and coloured by direction —
   the direction coming from ODR_CREDITS_HISTORY::direction() so the sign, the
   colour and the badge cannot disagree.

   The row is flex with items aligned to the top, which is what puts the money
   block in the card's top-right on a phone without a second set of rules —
   the same behaviour My Projects settled for money on a card.
   --------------------------------------------------------------- */
.pcoded-content.odr-credits .odr-cr-row{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;}
.pcoded-content.odr-credits .odr-cr-main{min-width:0;flex:1 1 auto;}
.pcoded-content.odr-credits .odr-cr-desc{display:block;font-weight:600;color:var(--re-dash-fg);line-height:1.4;}
/* The named id. Its own line, between the sentence and the date, because it is the
   one thing on the row a customer quotes to support or clicks through to. */
.pcoded-content.odr-credits .odr-cr-ref{display:block;font-size:12.5px;color:var(--re-dash-fg-secondary);margin-top:4px;}
.pcoded-content.odr-credits .odr-cr-ref a{color:var(--re-dash-info-dark);font-weight:600;}
.pcoded-content.odr-credits .odr-cr-meta{display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  font-size:12px;color:var(--re-dash-fg-muted);margin-top:5px;}
.pcoded-content.odr-credits .odr-cr-money{flex:0 0 auto;text-align:right;white-space:nowrap;}
.pcoded-content.odr-credits .odr-cr-amt{display:block;font-size:18px;font-weight:600;line-height:1.2;}
.pcoded-content.odr-credits .odr-cr-amt--in{color:var(--re-dash-success-darker);}
.pcoded-content.odr-credits .odr-cr-amt--out{color:var(--re-dash-danger-dark);}
.pcoded-content.odr-credits .odr-cr-amt--hold{color:var(--re-dash-warning-dark);}
.pcoded-content.odr-credits .odr-cr-bal{display:block;font-size:11.5px;color:var(--re-dash-fg-muted);margin-top:4px;}
@media (max-width:768px){
  /* A phone has no width to spare for a 16px gutter between a sentence and a
     number, and the amount can afford to give a point back. */
  .pcoded-content.odr-credits .odr-cr-row{gap:10px;}
  .pcoded-content.odr-credits .odr-cr-amt{font-size:17px;}
  .pcoded-content.odr-credits .odr-cr-bal{font-size:11px;}
}

/* The empty My Projects table, when a filter is what emptied it. DataTables
   centres td.dataTables_empty, so this only has to say the thing clearly.
   Built in my-account.js — see the note there for why it is scoped here and
   not made a language option every table inherits. */
.pcoded-content .odr-empty{padding:26px 14px;}
.pcoded-content .odr-empty-head{font-size:15px;font-weight:600;color:var(--re-dash-fg);margin:0 0 6px;}
.pcoded-content .odr-empty-filters{font-size:12.5px;color:var(--re-dash-fg-muted);margin:0 0 14px;}
.pcoded-content .odr-empty-filters span{color:var(--re-dash-fg-secondary);font-weight:600;}
.pcoded-content .odr-empty-acts{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin:0;}
.pcoded-content .odr-act{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px;}
.pcoded-content .odr-help{display:block;margin-top:5px;font-size:11px;color:var(--re-dash-fg-muted);text-align:right;line-height:1.4;max-width:250px;margin-left:auto;white-space:normal;overflow-wrap:anywhere;}
.pcoded-content .odr-help b{color:#e08a00;}
.pcoded-content .odr-wait{display:inline-flex;align-items:center;gap:6px;color:var(--re-dash-info);font-weight:700;font-size:12.5px;font-family:'Open Sans',sans-serif;}
.btn{font-family:'Open Sans',sans-serif;font-weight:500;border-radius:8px;font-size:12.5px;padding:8px 14px;line-height:1.1;text-transform:none;}
.btn-success{background:var(--re-dash-success);border-color:var(--re-dash-success);color:var(--re-dash-bg);}
.btn-success:hover{background:var(--re-dash-success-dark);border-color:var(--re-dash-success-dark);}
.btn-outline-success{color:var(--re-dash-success-dark);border-color:#bfe6c3;background:var(--re-dash-bg);}
.btn-outline-success:hover{background:var(--re-dash-success-soft);color:var(--re-dash-success-dark);}
.btn-outline-secondary{color:var(--re-dash-fg-secondary);border-color:var(--re-dash-border);background:var(--re-dash-bg);}
.btn-outline-secondary:hover{border-color:#cfd8e0;color:var(--re-dash-fg);}
.btn-danger{background:var(--re-dash-danger);border-color:var(--re-dash-danger);color:var(--re-dash-fg-inverse);}
.btn-danger:hover{background:var(--re-dash-danger-dark);border-color:var(--re-dash-danger-dark);}
.btn-outline-danger{color:var(--re-dash-danger);border-color:var(--re-dash-danger);background:var(--re-dash-bg);}
.btn-outline-danger:hover{background:var(--re-dash-danger-soft);color:var(--re-dash-danger);}
.btn-warning{background:var(--re-dash-warning);border-color:var(--re-dash-warning);color:var(--re-dash-fg-inverse);}
.btn-warning:hover{background:var(--re-dash-warning-dark);border-color:var(--re-dash-warning-dark);}
.btn-outline-warning{color:var(--re-dash-warning);border-color:var(--re-dash-warning);background:var(--re-dash-bg);}
.btn-outline-warning:hover{background:var(--re-dash-warning-soft);color:var(--re-dash-warning);}
.btn-info{background:var(--re-dash-info);border-color:var(--re-dash-info);color:var(--re-dash-fg-inverse);}
.btn-info:hover{background:var(--re-dash-info-dark);border-color:var(--re-dash-info-dark);}
.btn-outline-info{color:var(--re-dash-info);border-color:var(--re-dash-info);background:var(--re-dash-bg);}
.btn-outline-info:hover{background:var(--re-dash-info-soft);color:var(--re-dash-info);}
/* The 42px control height is for TEXT INPUTS AND SELECTS in the filter strip.
   `all-custom-filter` is also stamped on every checkbox and radio by
   rel_create_checkboxes_from_array(), so without the :not() guards this rule
   stretched each checkbox to 42px tall — which is where the huge vertical gaps
   in the Lead Status filter grid came from. The boxes are 13px; the spacing was
   the input, not the layout. */
.pcoded-content .all-custom-filter:not([type="checkbox"]):not([type="radio"]),.pcoded-content .select2-container--plain .select2-selection,
.pcoded-content .all-custom-filter:not([type="checkbox"]):not([type="radio"]),.pcoded-content .select2-container--plain .select2-selection,
.pcoded-content .all-custom-filter:not([type="checkbox"]):not([type="radio"]),.pcoded-content .select2-container--plain .select2-selection,
.pcoded-content .all-custom-filter:not([type="checkbox"]):not([type="radio"]),.pcoded-content .select2-container--plain .select2-selection,
/* No !important: `.pcoded-content .all-custom-filter` is specificity (0,2,0)
   against AdminDek's `.form-control` at (0,1,0), and this sheet loads after
   theirs — so the cascade already carries it. The !important here was fighting
   a battle that was never happening. Sizing comes from tokens so every control
   in the strip shares one definition. */
.pcoded-content .all-custom-filter:not([type="checkbox"]):not([type="radio"]), .pcoded-content .select2-container--plain .select2-selection{height:var(--re-dash-control-h);min-height:var(--re-dash-control-h);border:1px solid var(--re-dash-border);border-radius:var(--re-dash-control-radius);font-size:13px;color:var(--re-dash-fg);}
.pcoded-content .select2-container--plain .select2-selection--single{display:flex;align-items:center;padding:0 12px;}
.pcoded-content .select2-container{width:100%!important;}
.pcoded-content .odr-cl{display:none;}
/* ---- mobile: reflow rows to cards ---- */
@media (max-width:768px){
  .pcoded-content #dt-ajax-data-tables thead{display:none;}
.pcoded-content #dt-ajax-data-tables, .pcoded-content #dt-ajax-data-tables tbody{display:block;width:100%;min-width:0;}
  .pcoded-content .card-body{overflow-x:hidden;}
  .pcoded-content #dt-ajax-data-tables tbody tr{display:block;border:1px solid var(--re-dash-border);border-radius:12px;padding:4px 2px;margin-bottom:12px;box-shadow:0 1px 2px rgba(16,38,48,.05);}
  .pcoded-content #dt-ajax-data-tables tbody tr:hover{background:var(--re-dash-bg);}
  .pcoded-content #dt-ajax-data-tables tbody td{display:flex!important;justify-content:space-between;align-items:center;gap:14px;border:none;padding:8px 14px;width:auto;font-size:13px;}
  .pcoded-content #dt-ajax-data-tables tbody td:first-child{display:block!important;padding-bottom:4px;}
  .pcoded-content #dt-ajax-data-tables tbody td:last-child{display:block!important;border-top:1px solid #eef2f5;margin-top:4px;padding-top:12px;}
  .pcoded-content .odr-cl{display:inline-block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--re-dash-fg-muted);}
  .pcoded-content .odr-act{justify-content:stretch;}
  .pcoded-content .odr-act .btn{flex:1 1 auto;justify-content:center;}
  .pcoded-content .odr-help{text-align:left;max-width:none;margin-left:0;}
  /* On a phone the money is ONE figure in the card's top-right — "Fee ₹149" while owed,
     "Paid ₹184" once not — rather than a labelled row halfway down (owner, 2026-09-03). */
  .pcoded-content #dt-ajax-data-tables tbody td:first-child{display:block!important;}
  .pcoded-content .idrow .mfee{display:block;text-align:right;white-space:nowrap;flex:0 0 auto;font-size:13px;}
  .pcoded-content .idrow .mfee .ml{display:block;font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--re-dash-fg-muted);margin-bottom:2px;}
  /* An empty scores cell is a labelled row that says nothing — it costs a line. */
  .pcoded-content #dt-ajax-data-tables tbody td:has(> .chip.none){display:none!important;}
  .pcoded-content .odr-sub{max-width:none;}
.pcoded-content tr.odr-row--pay td:first-child, .pcoded-content tr.odr-row--upsell td:first-child{box-shadow:none;}
  .pcoded-content #dt-ajax-data-tables tbody tr.odr-row--pay{border-left:3px solid #e08a00;}
  .pcoded-content #dt-ajax-data-tables tbody tr.odr-row--upsell{border-left:3px solid var(--re-dash-success);}
.pcoded-content #dt-ajax-data-tables td.dtr-control, .pcoded-content #dt-ajax-data-tables tr.child{display:none!important;}
}
/* ---------------------------------------------------------------
   Unified activities popup (.odr-activity-wrap)
   Rendered by ODR_ACTIVITY_LOG; behaviour in theme/admin/ajaxactions.js.
   Scoped to the wrap so it can't leak into the other modal tables.
   --------------------------------------------------------------- */
/* Fourteen buttons in a panel about 500px wide will always wrap. The point is
   that it wraps TIDILY — the previous sizing left a single orphan on its own
   line — so the buttons are tightened and the count badge stops carrying
   Bootstrap's default padding. */
.odr-activity-filters { gap: 3px; }
.odr-activity-filters .odr-activity-filter {
  border-radius: 3px;
  padding: 3px 8px;
  font-size: 11.5px;
  line-height: 1.5;
}
.odr-activity-filters .odr-activity-count {
  padding: 1px 4px;
  font-size: 10px;
  font-weight: 700;
}
/* Calls / Notes / Follow-ups / Lead all come from GrowYu. A dot marks them as
   one set without a second row of chrome, so the bar still reads as one list of
   filters rather than two competing ones. */
.odr-activity-filters .odr-activity-filter--growyu::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 5px;
  border-radius: 50%;
  background: var(--re-dash-info);
  vertical-align: middle;
}
.odr-activity-filters .odr-activity-filter--growyu.active::before {
  background: var(--re-dash-fg-inverse);
}
/* The active filter needs to read as selected against the outline buttons. */
.odr-activity-filters .odr-activity-filter.active {
  background: var(--g, var(--re-dash-brand));
  border-color: var(--g, var(--re-dash-brand));
  color: var(--re-dash-bg);
}
.odr-activity-filters .odr-activity-count:empty { display: none; }

.odr-activity-toolbar { gap: 8px; }
.odr-activity-toolbar-actions { display: flex; align-items: center; gap: 8px; }

/* TWO columns: a fixed meta rail and everything else for the message.
   Prod data drove this — median message is 13-200 chars (longest 498), while
   S.No/time/user are fixed-width by nature. The old 4-column grid gave ~55% of
   the popup to three narrow columns and wrapped every message into a ragged
   stack in what was left. */
.odr-activity-table { font-size: 13px; }
.odr-activity-table th,
.odr-activity-table td { vertical-align: top; }
.odr-activity-table thead th {
  border-top: 0;
  border-bottom: 1px solid #e5e8ec;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #8a94a6;
  padding-bottom: 6px;
}
/* Rows separate by a hairline rule, not a full grid — a bordered table at this
   density reads as a spreadsheet and fights the message text for attention. */
.odr-activity-table tbody td {
  border-top: 0;
  border-bottom: 1px solid #eef1f4;
  padding: 10px 12px 10px 0;
}
.odr-activity-table tbody tr:last-child td { border-bottom: 0; }

.odr-activity-th-meta,
.odr-activity-table .odr-activity-meta {
  width: 155px;
  min-width: 155px;
  white-space: nowrap;
}
.odr-activity-table .odr-activity-sno {
  display: inline-block;
  min-width: 20px;
  margin-bottom: 2px;
  font-size: 11px;
  font-weight: 600;
  color: #b6bdc9;
}
.odr-activity-table .odr-activity-sno:empty { display: none; }
.odr-activity-table .odr-activity-when { font-weight: 600; color: #3b4453; }
.odr-activity-table .odr-activity-date { font-size: 11px; color: #8a94a6; }
.odr-activity-table .odr-activity-who { margin-top: 4px; font-weight: 600; }
.odr-activity-table .odr-activity-role {
  font-size: 11px;
  color: #8a94a6;
  text-transform: lowercase;
}

/* The message column takes the remaining width. Activity messages carry pasted
   URLs and long order IDs — wrap rather than force the popup to scroll sideways. */
.odr-activity-table .odr-activity-what {
  word-break: break-word;
  overflow-wrap: anywhere;
  white-space: normal;
}
.odr-activity-table .odr-activity-label {
  font-weight: 600;
  color: #2b3445;
}
.odr-activity-table .odr-activity-message { color: #55607a; }
.odr-activity-table .odr-activity-message:empty { display: none; }

/* GrowYu rows are merged in client-side; tint them so it stays obvious which
   entries came from the CRM rather than this app. */
.odr-activity-table tr[data-source="growyu"] { background: #f6fbff; }

/* Narrow drawers: the fixed meta rail stops being affordable, so stack it above
   the message as one line instead of letting it squeeze the text to a column of
   single words. */
@media (max-width: 575.98px) {
  .odr-activity-table thead { display: none; }
  .odr-activity-table tbody tr { display: block; border-bottom: 1px solid #eef1f4; }
  .odr-activity-table tbody tr:last-child { border-bottom: 0; }
  .odr-activity-table tbody td { display: block; width: auto; border-bottom: 0; padding: 0; }
  .odr-activity-table .odr-activity-meta {
    width: auto;
    min-width: 0;
    white-space: normal;
    padding-top: 10px;
  }
  .odr-activity-table .odr-activity-meta > span { display: inline !important; }
  .odr-activity-table .odr-activity-meta > span + span::before {
    content: "·";
    margin: 0 5px;
    color: #c9cfd9;
  }
  .odr-activity-table .odr-activity-what { padding-bottom: 10px; }
}

/* Datatables: no zebra striping — cleaner scan, lets status/badges carry the
   colour. Global to every .rel-dt-common table. Additive; revert = delete this block. */
table.rel-dt-common.table-striped tbody > tr:nth-of-type(odd),
table.rel-dt-common tbody > tr.odd,
table.rel-dt-common tbody > tr.even { background-color: transparent; }

/* =========================================================================
   Readable danger/error alerts (theme-wide). pages.css restyles .alert-danger
   to white-bg + light-red text, which collides with .text-white (white-on-white).
   Restore contrast in all three combinations without touching pages.css or the
   other alert types. Lives here (re-dash style.css loads raw on the dashboard;
   omak's style-admin-override.css is bundled and doesn't reach these screens).
   ========================================================================= */
.alert.alert-danger              { background:#fde8ea; border-color:#f5c2c7; color:#b02a37; }
.alert.alert-danger.text-white   { background:#dc3545; border-color:#dc3545; }   /* solid red so white text reads */

/* Bootstrap's `a:not([href]):not([tabindex]) { color:inherit }` (specificity 0,2,1)
   outguns `.btn-re` (0,1,0), so href-less anchor buttons — every .modal_actions
   trigger — render #333 text on the #37474F button. Restore the button colour. */
a.btn-re:not([href]):not([tabindex]),
a.btn-re:not([href]):not([tabindex]):hover,
a.btn-re:not([href]):not([tabindex]):focus,
a.btn-re-a:not([href]):not([tabindex]),
a.btn-re-a:not([href]):not([tabindex]):hover,
a.btn-re-a:not([href]):not([tabindex]):focus { color:var(--re-dash-bg); }

/* =========================================================================
   Stacked slide-in panels (RelSlide) — GTM-style right-hand drawers that stack
   N deep. Each new panel slides over the previous, which shifts left + dims.
   One ESC / close / backdrop-click pops only the TOP panel. VIEW/ACTION popups;
   confirmations stay centered. (Engine JS lives in omak ajaxactions.js.)
   ========================================================================= */
/* Reuses the table-page design tokens from line 439 (--g/--ink/--mut/--sub/--bd),
   same values, not new colours. RelSlide.ensureRoot() (omak ajaxactions.js)
   appends #rel-slidein-root straight onto <body>, so it is a SIBLING of
   .odr-projects/.odr-users/etc, never a descendant — the tokens declared only
   on those six classes do not reach in here on their own. Redeclared at the
   same values so the help panel below can use the same token names, since it
   opens from screens that carry none of those wrapper classes at all
   (Approvals, Issues, Vendor & Expenses, global search). */

.rel-si-root { position:fixed; inset:0; z-index:1090; pointer-events:none; visibility:hidden; }
.rel-si-root.rel-si-open { pointer-events:auto; visibility:visible; }

.rel-si-backdrop { position:absolute; inset:0; background:rgba(17,21,30,.46); opacity:0;
    transition:opacity .5s cubic-bezier(.16,1,.3,1); }
.rel-si-root.rel-si-open .rel-si-backdrop { opacity:1; }

/* Drawer motion: ease-out-expo — a quick launch that decelerates into a soft settle,
   the curve premium drawers use. A hair slower than a snap so it reads as deliberate. */
.rel-si-panel { position:absolute; top:0; right:0; height:100%; width:clamp(340px,46vw,760px);
    max-width:96vw; background:var(--re-dash-bg); box-shadow:-18px 0 50px rgba(17,21,30,.22); display:flex;
    flex-direction:column; transform:translateX(100%);
    transition:transform .52s cubic-bezier(.16,1,.3,1), filter .4s ease, box-shadow .4s ease;
    will-change:transform; }
.rel-si-panel.rel-si-in   { transform:translateX(0); }
.rel-si-panel.rel-si-out  { transform:translateX(100%); box-shadow:-6px 0 20px rgba(17,21,30,.10); }

/* Depth is UNBOUNDED — the stack takes N panels. Every buried-panel property is a
   clamped formula of --depth (0 = top) rather than a per-level rule, so level 12
   degrades exactly as gracefully as level 2: offset, shrink and dimming each ease
   toward a ceiling instead of marching off-screen. Add a level, change nothing. */
.rel-si-panel.rel-si-behind {
    transform:translateX(calc(-1 * min(var(--depth,1) * 22px, 96px)))
              scale(calc(1 - min(var(--depth,1) * 0.014, 0.07)));
    filter:brightness(calc(1 - min(var(--depth,1) * 0.055, 0.24)));
    box-shadow:-8px 0 24px rgba(17,21,30,.12);
    /* The exposed left sliver is a click target: click it to pop back to that level.
       Children go pointer-events:none so the click always lands on the panel itself. */
    cursor:pointer;
}
.rel-si-panel.rel-si-behind > * { pointer-events:none; }
.rel-si-panel.rel-si-behind::after { content:''; position:absolute; inset:0;
    background:linear-gradient(90deg, rgba(12,189,24,.06), transparent 40%);
    opacity:0; transition:opacity .2s ease; pointer-events:none; }
.rel-si-panel.rel-si-behind:hover::after { opacity:1; }

/* Header: a quiet title bar, not a brand banner.
   A full-bleed var(--re-dash-brand) block is the loudest thing on screen in a panel whose job
   is to present dense content (tables, forms, help copy) — it pulled the eye away
   from the content every time a drawer opened, and stacked drawers repeated it.
   Brand stays as a thin accent rule; the title carries the weight instead. */
.rel-si-head { flex:0 0 auto; display:flex; align-items:center; justify-content:space-between;
    gap:12px; padding:14px 20px; background:var(--re-dash-bg); color:#1f2530;
    border-top:3px solid var(--re-dash-brand); border-bottom:1px solid #e9ecf1; }
.rel-si-head .rel-si-titlewrap { display:flex; align-items:center; gap:10px; min-width:0; }
.rel-si-title { margin:0; font-size:15px; font-weight:600; line-height:1.35; color:#1f2530;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rel-si-headactions { flex:0 0 auto; display:flex; align-items:center; gap:8px; }
.rel-si-close { flex:0 0 auto; background:transparent; border:0; color:#98a1b0; width:30px;
    height:30px; border-radius:6px; font-size:22px; line-height:1; cursor:pointer;
    transition:background .15s ease, color .15s ease; }
.rel-si-close:hover { background:#f2f4f7; color:#1f2530; }
.rel-si-close:focus-visible { outline:2px solid var(--re-dash-brand); outline-offset:2px; }
/* Only rendered from level 2 up: X pops ONE panel, this dismisses the whole stack —
   without it a 6-deep stack needs six clicks to get back to the page. */
.rel-si-closeall { flex:0 0 auto; background:transparent; border:1px solid #dfe3e8;
    color:#6b7280; height:30px; padding:0 10px; border-radius:6px; font-size:12px; font-weight:600;
    letter-spacing:.02em; cursor:pointer; white-space:nowrap;
    transition:background .15s ease, border-color .15s ease, color .15s ease; }
.rel-si-closeall:hover { background:#f5f7f9; border-color:#c9cfd9; color:#1f2530; }
.rel-si-closeall:focus-visible { outline:2px solid var(--re-dash-brand); outline-offset:2px; }

.rel-si-body { flex:1 1 auto; overflow-y:auto; overflow-x:hidden; padding:20px;
    -webkit-overflow-scrolling:touch;
    /* Content settles in just after the drawer lands — a subtle fade + rise that
       makes the panel feel layered rather than a flat slab arriving all at once. */
    opacity:0; transform:translateY(12px);
    transition:opacity .45s ease .13s, transform .5s cubic-bezier(.16,1,.3,1) .13s; }
.rel-si-panel.rel-si-in .rel-si-body { opacity:1; transform:translateY(0); }
.rel-si-head { transition:opacity .3s ease; }
.rel-si-panel.rel-si-out .rel-si-head, .rel-si-panel.rel-si-out .rel-si-body { opacity:0; }
.rel-si-loading { display:flex; align-items:center; gap:10px; color:#6b7280; padding:30px 4px; font-size:15px; }
.rel-si-depth { font-size:11px; font-weight:600; letter-spacing:.04em; background:rgba(255,255,255,.18);
    padding:2px 8px; border-radius:20px; }

body.rel-si-lock { overflow:hidden; }
@media (prefers-reduced-motion:reduce) { .rel-si-panel, .rel-si-backdrop { transition-duration:.01ms; } }

/* =========================================================================
   rel-gs — global search results, inside a RelSlide drawer.

   Deliberately not styled like the ~170 form fragments that share the drawer.
   Those answer "fill this in for the thing you clicked". This one answers
   "here is everything that matches what you typed", which is a scan surface:
   you read down it, compare rows, and pick. So it gets a dark sticky header
   (the search bar has to stay reachable while the list scrolls), a neutral
   paper background so the white cards separate from it, and a coloured rail
   per record type that tells you what kind of thing a card is before you read
   a word of it.

   Colour is the ONLY thing carrying record type here, so each rail pairs with
   a written group heading above it — the rail is a speed-up for people who
   already know the scheme, never the sole channel.
   Markup: odr_global_search_results_html() in re-dash.
   ========================================================================= */
.rel-gs { display:flex; flex-direction:column; min-height:0; height:100%; background:#f4f6f8; }

/* Sticky, because refining the term is the most likely next action when a
   search returns more than one thing — scrolling to the bottom of 25 results
   must not put the way to narrow them off screen. */
.rel-gs__head { flex:0 0 auto; background:#1f2530; color:var(--re-dash-bg); padding:14px 20px 12px; }
.rel-gs__searchrow { display:flex; align-items:center; gap:8px; }
.rel-gs__input { flex:1 1 auto; min-width:0; height:38px; border:1px solid rgba(255,255,255,.18);
    background:rgba(255,255,255,.08); color:var(--re-dash-bg); border-radius:8px; padding:0 12px; font-size:14px; }
.rel-gs__input::placeholder { color:rgba(255,255,255,.5); }
.rel-gs__input:focus { outline:none; border-color:var(--re-dash-brand); background:rgba(255,255,255,.14); }
.rel-gs__go { flex:0 0 auto; width:38px; height:38px; border:0; border-radius:8px; cursor:pointer;
    background:var(--re-dash-brand); color:var(--re-dash-bg); font-size:15px; line-height:1; transition:filter .15s ease; }
.rel-gs__go:hover { filter:brightness(1.08); }
.rel-gs__go:focus-visible { outline:2px solid var(--re-dash-bg); outline-offset:2px; }
.rel-gs__help { flex:0 0 auto; display:inline-flex; align-items:center; gap:5px; height:38px;
    padding:0 12px; border:1px solid rgba(255,255,255,.28); border-radius:8px; cursor:pointer;
    font-size:12px; font-weight:600; letter-spacing:.02em; color:var(--re-dash-bg); white-space:nowrap;
    transition:background .15s ease; }
.rel-gs__help:hover { background:rgba(255,255,255,.14); }

.rel-gs__summary { margin:10px 0 0; font-size:12.5px; color:rgba(255,255,255,.72); }
.rel-gs__summary b { color:var(--re-dash-bg); }
/* Says which matchers ran. Ambiguous terms fan out to several, and without this
   a lead card under a name search looks like a mistake. */
.rel-gs__matched { display:inline-block; margin-left:6px; padding:1px 8px; border-radius:20px;
    background:rgba(255,255,255,.10); font-size:11px; letter-spacing:.02em; }

.rel-gs__scroll { flex:1 1 auto; min-height:0; overflow-y:auto; padding:16px 20px 24px;
    -webkit-overflow-scrolling:touch; }

.rel-gs__notice { margin:0 0 14px; padding:9px 12px; border-radius:8px; font-size:12.5px;
    background:#fff7e6; border:1px solid #f0d199; color:#7a5a12; }
/* Neutral, not alarming: "you may not search this" is a statement of scope, not
   an error the reader can act on. */
.rel-gs__notice--locked { background:#eef1f5; border-color:#d5dae0; color:#4b5563; }

.rel-gs__group { margin:0 0 18px; }
.rel-gs__group:last-child { margin-bottom:0; }
.rel-gs__grouphead { margin:0 0 8px; font-size:11px; font-weight:700; letter-spacing:.08em;
    text-transform:uppercase; color:#6b7280; display:flex; align-items:center; gap:8px; }
.rel-gs__groupcount { background:#e3e7ec; color:#4b5563; border-radius:20px; padding:1px 8px;
    font-size:11px; font-weight:600; letter-spacing:0; }

.rel-gs__card { background:var(--re-dash-bg); border:1px solid #e5e8ec; border-left-width:4px;
    border-left-color:#cbd2da; border-radius:10px; padding:12px 14px; margin-bottom:10px;
    transition:box-shadow .15s ease, border-color .15s ease; }
.rel-gs__card:hover { box-shadow:0 3px 12px rgba(17,21,30,.08); }
.rel-gs__card:last-child { margin-bottom:0; }
.rel-gs__card--project { border-left-color:var(--re-dash-brand); }
.rel-gs__card--payment { border-left-color:#e0a42c; }
.rel-gs__card--user    { border-left-color:#2f7ee0; }
.rel-gs__card--lead    { border-left-color:#8b5cf6; }
/* Archive-host rows in the user-projects slide-in: same card, visibly dormant. */
.rel-gs__card--project-archived { border-left-color:#cbd2da; background:#f6f7f8; opacity:.85; }

/* Free text lines under the facts (filename, read-only remarks). anywhere-wrap
   because remarks and workflow-suffixed filenames must fold inside the drawer,
   never push past its right edge (owner ask, quick-task #1c).

   white-space:normal is what lets this class survive inside a datatable cell.
   This stylesheet sets `td, th { white-space: nowrap }` globally — which the
   codebase otherwise opts out of per-cell with `.text-wrap` (defined in
   omak-dash/theme/admin/style-admin-override.css, NOT by Bootstrap, which does
   not ship that utility in the bundle here) — and a note in a table INHERITS
   that nowrap, so overflow-wrap/word-break never get a chance to act: the line
   stays on one row and stretches its column until the columns beside it are
   squeezed off-screen (vendors table, 2026-08-29). The datatable builds its own
   <td> client-side, so there is no cell to put .text-wrap on; declaring it here
   makes the note wrap wherever it is used. In the search card the container
   already wraps, so this is a no-op there. */
.rel-gs__note { margin:8px 0 0; font-size:12px; color:#6b7280; max-width:100%;
    white-space:normal; overflow-wrap:anywhere; word-break:break-word; }
.rel-gs__note--remarks { font-style:italic; }
.rel-gs__note--danger { color:#c0392b; }

.rel-gs__cardtop { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.rel-gs__titlewrap { display:flex; align-items:baseline; flex-wrap:wrap; gap:8px; min-width:0; }
.rel-gs__title { margin:0; font-size:15px; font-weight:600; color:#1f2530; min-width:0;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* "why is this here" — the single most useful thing on a fanned-out search, and
   the reason a card that looks unrelated is explainable instead of suspicious. */
.rel-gs__why { flex:0 0 auto; font-size:10.5px; font-weight:600; letter-spacing:.03em;
    color:#6b7280; background:#f1f3f5; border-radius:20px; padding:2px 9px; white-space:nowrap; }
/* Top-right corner of the card: the service (what this project IS) beside the
   matched-on note. Report services read as quiet muted text — they are the
   default; a NON-report service wears the light info badge so the exception
   is spottable at a glance (owner ask 2026-08-13). */
.rel-gs__corner { flex:0 0 auto; display:flex; align-items:center; gap:6px; }
/* Status pill in the card corner. Background/ink come from the canonical
   get_select_class_for_status() classes (bg-info/bg-warning/… + text-white)
   printed alongside this one, so ONLY shape lives here — restating the colours
   would fork the status palette that the details-page hero already owns. */
.rel-gs__status { font-size:11px; font-weight:600; white-space:nowrap;
  padding:2px 9px; border-radius:11px; line-height:1.5; }
/* Customer name beside the project id: identifies the card, does not compete
   with the id for the heading role. */
.rel-gs__titlemeta { font-size:12px; font-weight:500; color:var(--re-dash-fg-secondary);
  min-width:0; overflow-wrap:anywhere; }
.rel-gs__service { font-size:11px; font-weight:600; color:var(--re-dash-fg-muted); white-space:nowrap; }
.rel-gs__service--badge { background:var(--re-dash-info-soft); color:var(--re-dash-info);
    border:1px solid var(--re-dash-info-soft); border-radius:20px; padding:2px 9px; }
.rel-gs__sub { margin:3px 0 0; font-size:12.5px; color:#6b7280; word-break:break-word; }

/* user-select:all — these get pasted into the Razorpay dashboard and into
   replies to customers, so one click should take the whole id, not a word. */
.rel-gs__chip { display:inline-flex; flex:0 0 auto; align-items:center; gap:6px; background:#f4f6f8;
    border:1px solid #e2e6ea; border-radius:6px; padding:2px 8px; font-size:11.5px;
    color:#39414d; user-select:all; }
.rel-gs__chip span { color:#94a0ae; font-size:10px; text-transform:uppercase; letter-spacing:.05em;
    user-select:none; }

.rel-gs__facts { display:flex; flex-wrap:wrap; gap:4px 16px; margin:10px 0 0; }
.rel-gs__fact { display:flex; align-items:baseline; gap:5px; margin:0; }
.rel-gs__fact dt { font-size:11px; color:#94a0ae; font-weight:500; }
.rel-gs__fact dd { margin:0; font-size:12.5px; color:#39414d; font-weight:600; }

.rel-gs__actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.rel-gs__btn { display:inline-block; padding:5px 12px; border-radius:6px; font-size:12.5px;
    font-weight:600; text-decoration:none; border:1px solid #d5dae0; color:#39414d; background:var(--re-dash-bg);
    transition:background .15s ease, border-color .15s ease; }
.rel-gs__btn:hover { background:#f4f6f8; border-color:#c3cad2; color:#1f2530; text-decoration:none; }
.rel-gs__btn--primary { background:var(--re-dash-brand); border-color:var(--re-dash-brand); color:var(--re-dash-bg); }
.rel-gs__btn--primary:hover { background:#0aa815; border-color:#0aa815; color:var(--re-dash-bg); }
.rel-gs__btn:focus-visible { outline:2px solid #1f2530; outline-offset:2px; }
/* Icon-only eye actions on the project card: bare glyphs, no box — a boxed
   icon button read as a broken chip next to the text buttons. Tooltip (and
   aria-label) carries the words. Neutral eye = admin Details view in the
   primary text colour; blue eye = customer-facing User View, same split the
   details-page header makes with its label-info button. */
.rel-gs__btn--icon { background:none; border:1px solid var(--re-dash-border); border-radius:5px;
    box-shadow:none; padding:4px 8px; font-size:17px; line-height:1; color:var(--re-dash-fg);
    display:inline-flex; align-items:center; }
.rel-gs__btn--icon:hover { background:none; border-color:var(--re-dash-border); color:var(--re-dash-fg); opacity:.7; }
.rel-gs__btn--icon:visited { color:var(--re-dash-fg); }
.rel-gs__btn--icon.rel-gs__btn--info,
.rel-gs__btn--icon.rel-gs__btn--info:visited { color:var(--re-dash-info); }
.rel-gs__btn--icon.rel-gs__btn--info:hover { color:var(--re-dash-info); opacity:.7; }
/* Unset, these fall through to the browser's UA :visited color once a link has
   been opened — indistinguishable from the card background on a solid button,
   unreadable on the outline one. Pin them back to the same color as the base/
   hover states above. */
.rel-gs__btn:visited { color:#39414d; }
.rel-gs__btn--primary:visited { color:var(--re-dash-bg); }

.rel-gs__iconstrip { display:flex; flex-wrap:wrap; align-items:center; gap:2px; margin-top:10px; }

.rel-gs__loading { display:flex; align-items:center; gap:10px; color:#6b7280; padding:30px 20px;
    font-size:15px; }

/* No-match state. Centred but NOT a shrug — it carries what the term was read
   as, why that found nothing, and the full accepted-format list, because a miss
   is the moment the reader most needs to know what this bar takes. */
.rel-gs__empty { padding:34px 12px 10px; text-align:center; }
.rel-gs__emptyicon { width:52px; height:52px; margin:0 auto 14px; border-radius:50%;
    background:#e8ebef; color:#94a0ae; display:flex; align-items:center; justify-content:center;
    font-size:22px; }
.rel-gs__emptytitle { margin:0 0 4px; font-size:15px; color:#1f2530; }
.rel-gs__emptytitle b { word-break:break-all; }
.rel-gs__emptyread { margin:0 0 14px; font-size:12.5px; color:#6b7280; }
.rel-gs__emptyread span { color:#39414d; font-weight:600; }

/* Left-aligned inside a centred block: these are sentences, and centred prose
   is measurably harder to read line-to-line. */
.rel-gs__hints { max-width:420px; margin:0 auto 18px; padding:11px 14px; text-align:left;
    list-style:none; background:var(--re-dash-bg); border:1px solid #e5e8ec; border-radius:10px;
    font-size:12.5px; line-height:1.55; color:#4b5563; }
.rel-gs__hints li { position:relative; padding-left:16px; margin-bottom:7px; }
.rel-gs__hints li:last-child { margin-bottom:0; }
.rel-gs__hints li::before { content:'→'; position:absolute; left:0; color:#94a0ae; }

.rel-gs__emptylabel { margin:0 0 9px; font-size:10.5px; font-weight:700; letter-spacing:.07em;
    text-transform:uppercase; color:#94a0ae; }
.rel-gs__formats { display:flex; flex-wrap:wrap; gap:6px; justify-content:center;
    max-width:440px; margin:0 auto; }
.rel-gs__format { background:var(--re-dash-bg); border:1px solid #e2e6ea; border-radius:6px; padding:3px 9px;
    font-size:11.5px; color:#39414d; cursor:default; }
.rel-gs__emptyhelp { margin:16px 0 0; font-size:12px; color:#94a0ae; }

@media (max-width:600px) {
    .rel-gs__searchrow { flex-wrap:wrap; }
    .rel-gs__help { order:3; width:100%; justify-content:center; }
}

/* =========================================================================
   rel-tabs — tabbed server-rendered fragments (Edit User popup: Profile /
   Preferences / Permissions). Switcher JS lives in omak ajaxactions.js and
   hides panes with the `hidden` attribute; the !important below is the guard
   for panes that also carry a display-setting utility class.
   ========================================================================= */
[data-rel-pane][hidden] { display:none !important; }

.rel-tabs .nav-tabs { border-bottom:1px solid #dee2e6; margin-bottom:0; }
.rel-tabs .nav-tabs .nav-link {
    background:transparent; border:1px solid transparent; border-bottom:0;
    border-top-left-radius:.25rem; border-top-right-radius:.25rem;
    padding:.6rem 1.1rem; font-size:14px; font-weight:600; color:#5b6b7b;
    cursor:pointer; transition:color .15s ease, background .15s ease;
}
.rel-tabs .nav-tabs .nav-link:hover  { color:var(--re-dash-brand); background:#f4f8f4; }
.rel-tabs .nav-tabs .nav-link.active { color:var(--re-dash-brand); background:var(--re-dash-bg);
    border-color:#dee2e6 #dee2e6 var(--re-dash-bg); box-shadow:inset 0 -2px 0 var(--re-dash-brand); }
.rel-tabs .nav-tabs .nav-link:focus-visible { outline:2px solid var(--re-dash-brand); outline-offset:-2px; }

/* Section heading inside a form — replaces the old full-width blue banners,
   which read as an error state rather than as a group label. */
.rel-form-section {
    margin:18px 0 10px; padding-bottom:6px; font-size:12px; font-weight:700;
    letter-spacing:.06em; text-transform:uppercase; color:#78909c;
    border-bottom:1px solid #eceff1;
}
.rel-form-section:first-child { margin-top:4px; }
.rel-access-readonly input[type=checkbox] { cursor:not-allowed; }

/* "Fix Text" — flag the fields it actually rewrote, so a no-op click is visibly a
   no-op rather than indistinguishable from a broken button. */
.rel-fixed-flash { background:#eafbe9 !important; border-color:var(--re-dash-brand) !important;
    transition:background .25s ease, border-color .25s ease; }

/* WARNING: never place a wildcard character right before a forward slash
   inside a comment in this file — that pair terminates the comment early
   and silently drops whatever rule follows. Always leave a space between. */
/* ===================== Admin All Users (.odr-users) =====================
   Same grammar as .odr-projects: muted uppercase micro-headers, hairline rows,
   one green accent.
   TABLE-CHROME rules below are scoped to `.pcoded-content` — AdminDek's own
   content wrapper, present on every dashboard page. They used to carry a
   hand-maintained list of seven screen classes, which is why a screen not on
   that list (Vendor & Expenses, for one) got none of this and looked
   unfinished beside the others.

   NOTE: My Leads (.odr-my-leads) was previously excluded here on purpose — it
   shares ODR_USERS::get_column_html() markup (ODR_MY_LEADS extends ODR_USERS,
   class.my_leads.php:332) but was not part of the original approved redesign.
   That exclusion is now GONE by owner decision (2026-08-06: one look
   everywhere), so My Leads picks up the same chrome as the rest. */
.pcoded-content .card.table-card{border:1px solid var(--re-dash-border);border-radius:12px;box-shadow:0 1px 2px rgba(16,38,48,.04),0 14px 34px -24px rgba(16,38,48,.22);}
.pcoded-content .card-header h5{font-family:'Quicksand',sans-serif;font-weight:700;color:var(--re-dash-fg);margin:0;}
.pcoded-content #dt-ajax-data-tables, .pcoded-content .odr-worklist-table{border-collapse:separate;border-spacing:0;}
.pcoded-content #dt-ajax-data-tables thead th, .pcoded-content .odr-worklist-table thead th{font-family:'Open Sans',sans-serif;text-transform:uppercase;font-size:10.5px;letter-spacing:.07em;color:var(--re-dash-fg-muted);font-weight:700;background:#fbfcfd;border-top:none;border-bottom:1px solid var(--re-dash-border);padding:12px 14px;vertical-align:middle;}
.pcoded-content #dt-ajax-data-tables tbody td, .pcoded-content .odr-worklist-table tbody td{border-top:none;border-bottom:1px solid #eef2f5;padding:14px;vertical-align:top;font-size:13px;color:var(--re-dash-fg-secondary);}
.pcoded-content #dt-ajax-data-tables tbody tr:hover, .pcoded-content .odr-worklist-table tbody tr:hover{background:#f8fbf8;}
.pcoded-content #dt-ajax-data-tables tbody tr:last-child td, .pcoded-content .odr-worklist-table tbody tr:last-child td{border-bottom:none;}
.pcoded-content #dt-ajax-data-tables.table-striped tbody tr:nth-of-type(odd), .pcoded-content .odr-worklist-table.table-striped tbody tr:nth-of-type(odd){background:transparent;}
/* 769-1200px ONLY. Below 769px the table becomes stacked cards (see the max-width:768px
   block above) and must be free to shrink to the viewport. This rule used to run to 0px:
   being LATER in the file at equal specificity, its min-width:900px beat that block's
   min-width:0, so every stacked row stayed 900px wide inside a ~276px phone and every
   VALUE sat off-screen in a region that could not be scrolled to. Labels rendered, data
   did not. Found by measurement 2026-09-03. */
@media (max-width:1200px) and (min-width:769px){.pcoded-content #dt-ajax-data-tables, .pcoded-content .odr-worklist-table{min-width:900px;}.pcoded-content .card-body{overflow-x:auto;}}
/* The customer list is six columns and fits a laptop card, so it does not need the 900px
   floor above — that exists for the wider admin tables. `.odr-projects` (bare) is used by
   exactly one template, view-view-projects2.php, so this cannot reach an admin screen. */
@media (max-width:1200px) and (min-width:769px){.pcoded-content.odr-projects #dt-ajax-data-tables{min-width:0;}}

/* CELL-LEVEL rules below apply under BOTH .pcoded-content and .pcoded-content — the
   markup they style is emitted by ODR_USERS::get_column_html() and is shared
   by both pages (see class.my_leads.php:332 delegating to parent). */

/* User cell */
.pcoded-content .odr-u-name{display:inline;font-family:'Quicksand',sans-serif;font-weight:700;font-size:14px;}
.pcoded-content .odr-u-name a{color:var(--re-dash-fg);text-decoration:none;}
.pcoded-content .odr-u-name a:hover{color:var(--re-dash-success-dark);}
.pcoded-content .odr-u-country{color:var(--re-dash-fg-muted);font-size:12px;margin-left:6px;}
.pcoded-content .odr-u-contact{display:block;font-size:12.5px;color:var(--re-dash-fg-secondary);margin-top:3px;}
.pcoded-content .odr-u-contact i{width:14px;margin-right:7px;color:var(--re-dash-fg-muted);}
.pcoded-content .odr-u-meta{display:block;font-size:11.5px;color:var(--re-dash-fg-muted);margin-top:7px;line-height:1.6;}
.pcoded-content .odr-u-gap{color:var(--re-dash-fg-placeholder);}
/* Remarks: odr-u-remarks wraps editable_columns()'s own markup verbatim
   (.rel-editable > .rel-editable-value + <textarea class="rel-editable-input">,
   see class.entity.php render_editable() "textarea" branch) -- we do not own
   that markup, only neutralise its global presentation (style-admin-override.css
   ".rel-editable-textarea .rel-editable-value" border/bg box and
   "span.rel-editable-value.no-value" red/bold) inside this cell. Handler,
   field name and tname are untouched -- presentation only, per spec. */
.pcoded-content .odr-u-remarks{display:block;margin-top:8px;font-size:12px;}
.pcoded-content .odr-u-remarks .rel-editable{display:inline-flex;}
.pcoded-content .odr-u-remarks .rel-editable-value{display:inline;width:auto;padding:0;border:none;background:none;font-size:12px;color:var(--re-dash-fg-secondary);white-space:normal;}
.pcoded-content .odr-u-remarks .rel-editable-value.no-value{color:var(--re-dash-fg-muted);font-weight:400;}
.pcoded-content .odr-u-remarks .rel-editable-value.no-value::before{content:"+ ";}
.pcoded-content .odr-u-remarks .rel-editable-value:hover{color:var(--re-dash-success-dark);cursor:pointer;text-decoration:underline;}
.pcoded-content .odr-u-remarks textarea{border:1px solid var(--re-dash-border);background:var(--re-dash-bg);padding:4px 6px;font-size:12px;width:100%;border-radius:4px;}
.pcoded-content .odr-u-remarks textarea:focus{border-color:var(--re-dash-success);outline:none;}

/* Location cell */
.pcoded-content .odr-u-place{display:block;color:var(--re-dash-fg);font-size:12.5px;}
.pcoded-content .odr-u-street{display:block;color:var(--re-dash-fg-muted);font-size:11.5px;margin-top:3px;max-width:240px;}

/* State cell */
.pcoded-content .odr-u-pills{display:flex;flex-wrap:wrap;gap:6px;}
/* --ok/--muted/--danger/--warning/--info modifiers on the shared .odr-pill
   base (defined once, style.css ~459). Also used (without the .odr-u-pills
   row wrapper) by .odr-offers (status + action chips), class.offers_used.php,
   class.transactions.php, view-sales-worklist.php and class.project_issues.php,
   replacing their old badge-info/badge-danger/label-danger. --warning/--info
   reuse the exact tokens the OTHER .odr-pill family (project status, ~461)
   already uses for the same colours — one palette, not a second one. */
.pcoded-content .odr-pill--ok{background:var(--re-dash-success-soft);color:var(--re-dash-success-dark);}
.pcoded-content .odr-pill--muted{background:var(--re-dash-border-light);color:var(--re-dash-fg-secondary);}
.pcoded-content .odr-pill--danger{background:var(--re-dash-danger-soft);color:var(--re-dash-danger);}
.pcoded-content .odr-pill--warning{background:var(--re-dash-warning-soft);color:var(--re-dash-warning);}
.pcoded-content .odr-pill--info{background:var(--re-dash-info-soft);color:var(--re-dash-info);}
.pcoded-content .odr-pill.user-action{cursor:pointer;}
.pcoded-content .odr-u-roles{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px;}
.pcoded-content .odr-u-role{font-size:10.5px;color:var(--re-dash-fg-muted);background:var(--re-dash-border-light);border:1px solid var(--re-dash-border);border-radius:4px;padding:2px 7px;}

/* Actions cell */
/* .odr-u-actions / .odr-act (+ --edit / --del modifiers) are also reused by
   .odr-offers' Code column (edit / delete / copy / clone ghost icons),
   replacing its old badge-primary/badge-danger/badge-info action buttons. */
.pcoded-content .odr-u-actions{display:flex;justify-content:flex-end;align-items:center;gap:2px;}
.pcoded-content .odr-act{position:relative;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:7px;color:var(--re-dash-fg-muted);cursor:pointer;transition:background .15s ease,color .15s ease;}
.pcoded-content .odr-act:hover{background:#eef2f6;color:var(--re-dash-fg-secondary);}
.pcoded-content .odr-act--edit:hover{background:var(--re-dash-success-soft);color:var(--re-dash-success-dark);}
.pcoded-content .odr-act--wa:hover{background:var(--re-dash-success-soft);color:#128c7e;}
.pcoded-content .odr-act--ban:hover{background:var(--re-dash-warning-soft);color:var(--re-dash-warning);}
.pcoded-content .odr-act--del:hover{background:var(--re-dash-danger-soft);color:var(--re-dash-danger);}
.pcoded-content .odr-act-count{position:absolute;top:-2px;right:-2px;background:var(--re-dash-success);color:var(--re-dash-bg);font-size:9px;font-weight:700;line-height:1;padding:2px 4px;border-radius:999px;}

/* Merged "User actions" / "Lead actions" slide-in (odr_user_row_actions_html() /
   ODR_USERS::get_extras('user_actions_html') and the Leads equivalent). Deliberately
   NOT scoped under .pcoded-content — this renders inside the RelSlide drawer
   (#rel-slidein-root, a <body> sibling), which is outside that scope; a
   .pcoded-content-scoped rule here would silently no-op the same way the row's own
   .odr-act icons did on the search card before today's fix. */
.odr-uap{display:flex;flex-direction:column;}
.odr-uap-row{display:flex;align-items:flex-start;gap:12px;padding:12px 4px;border-bottom:1px solid var(--re-dash-border-light);cursor:pointer;text-decoration:none;color:inherit;transition:background .15s ease;}
.odr-uap-row:last-child{border-bottom:none;}
.odr-uap-row:hover{background:var(--re-dash-bg-row-hover);}
.odr-uap-icon{flex:0 0 auto;width:30px;height:30px;border-radius:7px;display:inline-flex;align-items:center;justify-content:center;font-size:14px;color:var(--re-dash-fg-secondary);background:var(--re-dash-border-light);margin-top:1px;}
.odr-uap-body{display:flex;flex-direction:column;gap:1px;min-width:0;}
.odr-uap-label{font-size:13.5px;font-weight:600;color:var(--re-dash-fg);}
.odr-uap-desc{font-size:12px;color:var(--re-dash-fg-muted);}
.odr-uap-row--danger .odr-uap-icon{color:var(--re-dash-danger);background:var(--re-dash-danger-soft);}
.odr-uap-row--danger .odr-uap-label{color:var(--re-dash-danger);}
.odr-uap-row--danger:hover{background:var(--re-dash-danger-soft);}

/* Datatable filter header: shared by ALL admin datatable views (heading +
   button row is repositioned by omak-dash/theme/admin/ajaxactions.js onto
   one line — see the ".rel-dt-containers" wrap logic there). Kept here
   because style-admin-override.css (parent) needs a build step; this file
   is loaded raw on every environment. */
.re-dt-filter-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.5rem;}
.re-dt-filter-header .re-dt-filter-handle{display:inline-flex;align-items:center;gap:.4rem;}
.re-dt-filter-header .re-dt-filter-handle:focus{outline:2px solid var(--re-dash-brand);outline-offset:2px;}
.re-dt-filter-header .re-dt-filter-chevron{transition:transform .15s ease;}
.re-dt-filter-header.re-dt-filter-collapsed .re-dt-filter-chevron{transform:rotate(-90deg);}
/* Neutralize Bootstrap col-md-* width/margin on BOTH children (heading and
   button row) — some filter templates put "col-md-12" on the heading span
   too (e.g. filters-users.php). Leaving that 100%-width in place made the
   heading alone fill the whole flex line, pushing the button row onto its
   own line below (flex-wrap has to start a new line once the first item
   already claims 100% width) even though it was width:auto itself. */
.re-dt-filter-header > [class*="col-"]{flex:0 0 auto!important;width:auto!important;max-width:none!important;margin-top:0!important;padding-top:0!important;}
/* Button row: right-aligned, and lets its own buttons wrap onto extra lines
   (rather than overflow the card) on narrow viewports / views with more
   buttons (GST, Get Query, etc). */
.re-dt-filter-header .re-dt-filter-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:.35rem;max-width:100%!important;text-align:right;}

/* Vendor & Expenses renders 4 datatables on one page (one per tab), each with
   its own Refresh button. The parent's .btn-refresh-filter rule
   (omak-dash/theme/admin/style-admin-override.css — bundled via a webpack
   build step, not editable raw here) pins it position:fixed to one spot at
   the bottom of the viewport, so all four stack on top of each other instead
   of sitting in their own filter card. Un-fix it specifically inside a
   .tab-pane (the multi-datatable case); single-datatable pages have no
   .tab-pane ancestor around their filter bar, so their floating button is
   untouched. Descendant selector outweighs the parent's single-class rule on
   specificity alone, so no !important is needed. */
.tab-pane .btn-refresh-filter{position:static;bottom:auto;left:auto;z-index:auto;}

/* Site-wide "what is this screen" help trigger (mechanism in
   omak-dash/includes/functions-screen-help.php, rendered next to the page
   title's <h5> by rel_get_breadcrumb_html). Styled here — not in the
   parent's style-admin-override.css, which is bundled into a minified
   build and needs a build step — this file is loaded raw on every
   environment. Kept quiet: a muted "?" that only picks up colour on
   hover/focus, sized so it never competes with the title text. */
/* Findable by someone who does not know the feature exists — that is the whole job
   of this control, so it reads as a chip rather than a faint glyph. */
.rel-screen-help-trigger{display:inline-flex;align-items:center;justify-content:center;gap:.3rem;margin-left:.55rem;padding:.18rem .5rem;border:1px solid #cfe8d2;border-radius:999px;background:var(--re-dash-success-soft);color:#0a7a12;font-family:'Open Sans',sans-serif;font-size:.68rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;line-height:1;cursor:pointer;vertical-align:middle;transition:background .15s ease,border-color .15s ease;}
.rel-screen-help-trigger:hover,
.rel-screen-help-trigger:focus{background:#d8f0d5;border-color:var(--re-dash-brand);color:#0a6f10;outline:none;}
.rel-screen-help-trigger:focus-visible{outline:2px solid var(--re-dash-brand);outline-offset:2px;}
/* The theme styles .page-header.card .page-header-title i as a large rounded tile
   (that is the big green page icon). Our chip sits in that same block, so its icon
   inherits the tile and renders as a box overlapping the pill. Reset it here. */
.page-header.card .page-header-title .rel-screen-help-trigger i,
.rel-screen-help-trigger i{all:unset;display:inline-block;font-family:inherit;font-size:.85rem;line-height:1;color:inherit;background:none;border:0;box-shadow:none;padding:0;margin:0;width:auto;height:auto;border-radius:0;}
/* Help panel typography. These panels are READ, not skimmed past — they are the
   only place a screen's rules are written down — so they get reading measure,
   room between items, and a visible heading rhythm. Sections are separated by a
   rule rather than by whitespace alone: at six or seven sections the eye needs
   somewhere to stop. Applies to every registered help key, not just search.
   Colours run on the .odr-* table-page tokens (bridged onto .rel-si-root
   above) instead of one-off hex, so this panel and the redesigned tables read
   as one system. */
.rel-screen-help{max-width:68ch;font-size:.9rem;line-height:1.7;color:var(--re-dash-fg-secondary);}
/* The intro is the answer to "what is this screen for" — it has to be found
   without reading anything else, so it gets its own weight and the darkest
   ink colour rather than blending into the section bodies below it. */
.rel-screen-help__intro{margin-bottom:1.4rem;padding-bottom:1.1rem;
    border-bottom:1px solid var(--re-dash-border);font-size:1rem;font-weight:500;line-height:1.55;color:var(--re-dash-fg);}
.rel-screen-help__section{margin-bottom:1.5rem;padding-bottom:1.2rem;border-bottom:1px solid var(--re-dash-border);}
.rel-screen-help__section:last-child{margin-bottom:0;padding-bottom:0;border-bottom:0;}
/* A short brand-green tick ahead of the label — the same scan cue
   .workload-filter-bar uses below — so a section boundary is visible without
   reading the heading text first. */
.rel-screen-help__section h6{font-size:.74rem;font-weight:700;letter-spacing:.06em;
    text-transform:uppercase;color:var(--re-dash-fg-muted);margin:0 0 .65rem;padding-left:.55rem;
    border-left:2px solid var(--re-dash-success);line-height:1.3;}
.rel-screen-help__body ul{padding-left:1.2rem;margin-bottom:0;}
.rel-screen-help__body li{margin-bottom:.55rem;}
.rel-screen-help__body li:last-child{margin-bottom:0;}
.rel-screen-help__body li::marker{color:var(--re-dash-fg-muted);}
.rel-screen-help__body strong{color:var(--re-dash-fg);font-weight:600;}
/* Inline examples are things people copy the SHAPE of, so they need to read as
   data rather than as emphasised prose. Background has no token equivalent —
   kept as-is rather than borrowing an unrelated tint. */
.rel-screen-help__body code{background:#f4f6f8;border:1px solid var(--re-dash-border);border-radius:4px;
    padding:.05rem .35rem;font-size:.82rem;color:var(--re-dash-fg);white-space:nowrap;}
/* Quick search. Sticks to the top of the drawer's scroll so it stays reachable
   in a long panel — the reader refines the term while reading the results. */
/* A workload number that opens the projects behind it. Reads as interactive
   without becoming a link-blue eyesore inside a stat tile — a dotted underline
   that firms up on hover, which is the affordance a figure can carry without
   competing with the number itself. */
.workload-drill-trigger{cursor:pointer;border-bottom:1px dashed rgba(12,189,24,.55);transition:border-color .15s ease,color .15s ease;}
.workload-drill-trigger:hover,.workload-drill-trigger:focus{border-bottom-style:solid;border-bottom-color:var(--re-dash-brand);color:#0a8f14;}
.workload-drill-trigger .workload-badge{border-bottom:0;}
.workload-drill-trigger.is-active{border-bottom-style:solid;border-bottom-color:var(--re-dash-brand);color:#0a8f14;font-weight:700;}
.workload-drill .table td{vertical-align:middle;}

/* Says what the table is currently showing, and how to stop. A filter applied
   from another card is invisible otherwise — people conclude the table is broken
   rather than filtered. */
.workload-filter-bar{display:flex;align-items:center;gap:.75rem;margin:0 0 1rem;padding:.6rem .9rem;
    background:rgba(12,189,24,.08);border-left:3px solid var(--re-dash-brand);border-radius:0 6px 6px 0;}
.workload-filter-text{font-size:.85rem;font-weight:600;color:#0a6f10;}
.workload-filter-clear{margin-left:auto;appearance:none;background:var(--re-dash-bg);border:1px solid #cfe0d2;
    border-radius:6px;padding:.25rem .7rem;font-size:.78rem;font-weight:600;color:#0a6f10;cursor:pointer;}
.workload-filter-clear:hover{background:var(--re-dash-brand);border-color:var(--re-dash-brand);color:var(--re-dash-bg);}
.workload-filter-clear:focus-visible{outline:2px solid var(--re-dash-brand);outline-offset:2px;}

/* Given its own tinted, bordered pill rather than a bare bottom rule — the
   quick-search box is the fastest way through a long panel and should not
   read as just another form field. Still sticky, so it survives scrolling
   through a six-section screen like Vendor & Expenses or Global Search. */
.rel-screen-help__search{position:sticky;top:0;z-index:2;display:flex;align-items:center;gap:.6rem;
    margin:-.25rem 0 1.25rem;padding:.5rem .6rem;background:var(--re-dash-success-soft);border:1px solid var(--re-dash-border);border-radius:8px;}
.rel-screen-help__search-input{flex:1 1 auto;height:auto;padding:.4rem .7rem;border:1px solid var(--re-dash-border);
    border-radius:6px;font-size:.85rem;color:var(--re-dash-fg);background:var(--re-dash-bg);}
.rel-screen-help__search-input:focus{border-color:var(--re-dash-success);background:var(--re-dash-bg);box-shadow:0 0 0 3px rgba(12,189,24,.12);outline:none;}
.rel-screen-help__search-input::-webkit-search-cancel-button{cursor:pointer;}
.rel-screen-help__search-count{flex:0 0 auto;font-size:.72rem;font-weight:600;color:var(--re-dash-fg-muted);white-space:nowrap;}
.rel-screen-help__search-count:empty{display:none;}
/* The hit marker has to survive on a white panel without shouting — a wash plus
   weight, not the browser default's fluorescent yellow. No token matches this
   amber wash (--amber-soft is a different, more orange tint) so it is kept as
   its own value rather than swapped for one that would dim the highlight. */
.rel-screen-help__hit{background:#fff3bf;border-radius:2px;padding:0 .1rem;color:inherit;font-weight:600;}
.rel-screen-help__empty{margin:0;padding:.9rem 0;color:var(--re-dash-fg-muted);font-size:.85rem;}

/* =========================================================================
   Staff WhatsApp panel — one drawer, two tabs (Chat / Send template).
   Replaces the two separate popups that used to open from nine triggers.

   Design intent: an OPERATOR CONSOLE, not a consumer chat skin. Staff are not
   chatting; they are dispatching against Meta's 24-hour policy clock. So the one
   loud element is the WINDOW METER above the composer — it decides what staff are
   allowed to do, and when the window shuts it BECOMES the affordance (the composer
   is not rendered at all; see odr_wa_chat_tab_html()).

   Outbound bubbles are #e7f7e8 — a tint of RE's own brand green (var(--re-dash-brand)), NOT
   WhatsApp's #dcf8c6. Everything else is deliberately quiet.
   ========================================================================= */

/* The panel owns the full drawer body: no drawer padding, no drawer scroll. The
   thread is the only scroller, so the composer and meter stay pinned. RelSlide adds
   .rel-si-body--flush when a fragment declares data-si-flush (omak ajaxactions.js). */
.rel-si-body--flush { padding:0 !important; overflow:hidden !important; display:flex; flex-direction:column; }

.odr-wa-panel { display:flex; flex-direction:column; min-height:0; flex:1 1 auto;
    /* Positioned so it is its own select2 dropdownParent offset root (see
       odrWaRebindSelect2 in ajaxactions.js): select2 appends the open dropdown
       as a child of dropdownParent and absolutely positions it against
       dropdownParent's nearest POSITIONED ancestor. Left static, that ancestor
       was further up the drawer, so the open Mail Type list rendered offset
       from its own trigger with a visible gap instead of directly under it. */
    position:relative;
    color:var(--re-dash-fg); }

/* --- Context strip: who this conversation is with. Every send in the panel goes
   to this person, so it is never off-screen. */
.odr-wa-ctx { flex:0 0 auto; display:flex; align-items:center; justify-content:space-between;
    gap:12px; padding:12px 16px; border-bottom:1px solid var(--re-dash-border); background:var(--re-dash-bg); }
.odr-wa-ctx-who { display:flex; align-items:baseline; gap:10px; min-width:0; }
.odr-wa-ctx-name { font-weight:600; font-size:15px; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; }
.odr-wa-ctx-phone { font-size:12px; color:var(--re-dash-fg-muted); font-variant-numeric:tabular-nums;
    white-space:nowrap; }
.odr-wa-ctx-link { flex:0 0 auto; font-size:12px; font-weight:600; color:#0a7d12;
    text-decoration:none; border-bottom:1px solid transparent; }
.odr-wa-ctx-link:hover { color:#0a7d12; border-bottom-color:currentColor; }

/* --- Window status line: the same sentence the datatable badge's tooltip
   carries, spelled out so it is visible without a hover the moment the panel
   opens. */
.odr-wa-status-line { flex:0 0 auto; padding:8px 16px; font-size:12px;
    color:var(--re-dash-fg-muted); background:var(--re-dash-bg-header);
    border-bottom:1px solid var(--re-dash-border); }

/* --- Tabs */
.odr-wa-tabs { flex:0 0 auto; display:flex; gap:2px; padding:0 16px; background:var(--re-dash-bg);
    border-bottom:1px solid var(--re-dash-border); }
.odr-wa-tab { appearance:none; background:none; border:0; padding:10px 2px; margin-right:20px;
    font-size:13px; font-weight:600; color:var(--re-dash-fg-muted); cursor:pointer;
    border-bottom:2px solid transparent; }
.odr-wa-tab:hover { color:var(--re-dash-fg); }
.odr-wa-tab.is-on { color:var(--re-dash-fg); border-bottom-color:var(--re-dash-brand); }
.odr-wa-tab:focus-visible { outline:2px solid var(--re-dash-brand); outline-offset:2px; border-radius:2px; }

.odr-wa-pane { display:none; min-height:0; flex:1 1 auto; }
.odr-wa-pane.is-on { display:flex; flex-direction:column; }
.odr-wa-pane[data-wa-pane="template"].is-on { display:block; overflow-y:auto; padding:16px; }

/* Padding for every OTHER pane. Only the template pane had any, so Call, Email,
   Telegram and Debug rendered flush against the left edge and hard up under the
   tab strip — the "No call recorded for this customer yet." line sat in the top
   corner with nothing around it. The chat pane is excluded: it manages its own
   scroller and inner spacing, and padding here would indent every bubble. */
.odr-wa-pane.is-on:not([data-wa-pane="chat"]):not([data-wa-pane="template"]) {
    display:block; overflow-y:auto; padding:16px;
}

/* One rhythm for the lead-in text on every tab, so the description does not sit
   on top of the form it describes. */
.odr-wa-tab-desc { margin-bottom:14px; }

/* --- Chat pane */
.odr-wa-chat-panel { display:flex; flex-direction:column; min-height:0; flex:1 1 auto; }

/* The ONLY scroll container. Isolated with overscroll-behavior so reaching the top
   of the history never starts scrolling the page behind the drawer. */
.odr-wa-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain;
    background:var(--re-dash-bg-header); padding:14px 16px; scroll-behavior:smooth; }

.odr-wa-thread { display:flex; flex-direction:column; gap:2px; }
.odr-wa-thread--error { padding:12px 0; }

/* Day separator: a small-caps date sitting on a hairline. Structural, not decorative
   — it is the only thing that tells staff a two-minute gap from a two-week one. */
.odr-wa-day { position:relative; text-align:center; margin:16px 0 10px; }
.odr-wa-day::before { content:''; position:absolute; left:0; right:0; top:50%;
    border-top:1px solid var(--re-dash-border); }
.odr-wa-day span { position:relative; background:var(--re-dash-bg-header); padding:0 10px;
    font-size:10px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
    color:var(--re-dash-fg-muted); }

.odr-wa-row { display:flex; margin:3px 0; }
.odr-wa-in  { justify-content:flex-start; }
.odr-wa-out { justify-content:flex-end; }

.odr-wa-bubble { max-width:78%; padding:8px 11px 5px; border-radius:12px; font-size:13px;
    line-height:1.45; word-break:break-word; }
.odr-wa-in  .odr-wa-bubble { background:var(--re-dash-bg); border:1px solid var(--re-dash-border);
    border-top-left-radius:3px; }
.odr-wa-out .odr-wa-bubble { background:var(--re-dash-chat-out); border:1px solid var(--re-dash-chat-out-line);
    border-top-right-radius:3px; }
.odr-wa-bubble--failed { border-color:var(--re-dash-danger); }

.odr-wa-body a { color:#0a6ebd; text-decoration:underline; }
.odr-wa-head { font-weight:700; margin-bottom:4px; }
.odr-wa-body code { background:rgba(17,21,30,.06); padding:0 3px; border-radius:3px;
    font-size:12px; }
.odr-wa-faint { color:var(--re-dash-fg-muted); font-style:italic; }
.odr-wa-quote { color:var(--re-dash-fg-muted); }
.odr-wa-reaction { font-size:16px; }
.odr-wa-choice { display:inline-block; font-weight:600; }

/* Meta row: tabular figures so times line up down the whole thread. */
.odr-wa-meta { display:flex; align-items:center; justify-content:flex-end; gap:5px;
    margin-top:3px; font-size:10px; color:var(--re-dash-fg-muted);
    font-variant-numeric:tabular-nums; }
.odr-wa-tick { font-size:11px; line-height:1; }
.odr-wa-tick--read      { color:#0a86d8; }   /* blue, as on the customer's phone */
.odr-wa-tick--delivered,
.odr-wa-tick--sent      { color:var(--re-dash-fg-muted); }
.odr-wa-tick--failed    { color:var(--re-dash-danger); font-weight:700; }

/* Template/interactive buttons as chips under the bubble, like the customer sees. */
.odr-wa-btns { display:flex; flex-wrap:wrap; gap:5px; margin-top:7px;
    padding-top:7px; border-top:1px solid rgba(17,21,30,.08); }
.odr-wa-btn { font-size:11px; font-weight:600; color:#0a6ebd; background:rgba(10,110,189,.07);
    border-radius:4px; padding:3px 8px; }

/* Media = a named chip. Never an <img>: opening a thread would otherwise fire a
   request per image to the vendor CDN, and the panel must stay self-contained. */
.odr-wa-file { display:flex; align-items:center; gap:9px; margin-top:6px; padding:7px 9px;
    background:rgba(17,21,30,.04); border:1px solid rgba(17,21,30,.07); border-radius:8px; }
.odr-wa-file-icon { flex:0 0 auto; font-size:16px; line-height:1; }
.odr-wa-file-text { display:flex; flex-direction:column; min-width:0; }
.odr-wa-file-name { font-size:12px; font-weight:600; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; }
.odr-wa-file-sub { font-size:10px; color:var(--re-dash-fg-muted); text-transform:uppercase;
    letter-spacing:.04em; }
.odr-wa-file-sub a { color:#0a7d12; font-weight:700; text-decoration:none; }
.odr-wa-file-sub a:hover { text-decoration:underline; }

.odr-wa-err { margin-top:6px; font-size:11px; font-weight:600; color:var(--re-dash-danger); }

/* System log + internal note: centred, quiet, clearly not part of the conversation. */
.odr-wa-sys, .odr-wa-note { text-align:center; margin:8px 0; }
.odr-wa-sys span { display:inline-block; font-size:10px; color:var(--re-dash-fg-muted);
    background:rgba(17,21,30,.05); border-radius:20px; padding:3px 10px; }
.odr-wa-note { display:flex; align-items:center; justify-content:center; gap:6px;
    flex-wrap:wrap; }
.odr-wa-note-tag { font-size:9px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
    color:#6d28a8; background:rgba(109,40,168,.09); border-radius:3px; padding:2px 6px; }
.odr-wa-note-body { font-size:11px; color:#6d28a8; max-width:80%; }

.odr-wa-empty { display:flex; flex-direction:column; align-items:center; gap:4px;
    padding:44px 16px; text-align:center; }
.odr-wa-empty strong { font-size:14px; }
.odr-wa-empty span { font-size:12px; color:var(--re-dash-fg-muted); max-width:34ch; }

/* --- THE SIGNATURE: the window meter.
   States what staff may do, in words, right where they are about to act. */
.odr-wa-meter { flex:0 0 auto; padding:9px 16px 10px; background:var(--re-dash-bg);
    border-top:1px solid var(--re-dash-border); }
.odr-wa-meter-line { display:flex; align-items:center; justify-content:space-between;
    gap:10px; font-size:12px; }
.odr-wa-meter-line strong { font-weight:700; color:#0a7d12; }
.odr-wa-meter-left { color:var(--re-dash-fg-muted); font-variant-numeric:tabular-nums; }
.odr-wa-meter-bar { position:relative; height:3px; margin-top:7px; border-radius:2px;
    background:rgba(17,21,30,.08); overflow:hidden; }
.odr-wa-meter-bar > span { display:block; height:100%; background:var(--re-dash-brand);
    border-radius:2px; transition:width .4s ease; }
.odr-wa-meter--soon .odr-wa-meter-line strong { color:#a86a05; }
.odr-wa-meter--soon .odr-wa-meter-bar > span { background:var(--re-dash-warning); }

.odr-wa-meter--shut { background:#fff7f7; border-top-color:#f3c9cd; }
.odr-wa-meter--shut .odr-wa-meter-line strong { color:var(--re-dash-danger); }
.odr-wa-meter-why { margin:5px 0 0; font-size:11px; color:var(--re-dash-fg-muted); line-height:1.45; }
.odr-wa-gotmpl { appearance:none; background:none; border:1px solid var(--re-dash-danger);
    color:var(--re-dash-danger); font-size:11px; font-weight:600; border-radius:4px;
    padding:3px 9px; cursor:pointer; }
.odr-wa-gotmpl:hover { background:var(--re-dash-danger); color:var(--re-dash-bg); }
.odr-wa-gotmpl:focus-visible { outline:2px solid var(--re-dash-danger); outline-offset:2px; }

/* --- Composer. Only rendered while the window is open.
   The field used to sit on the grey canvas with a hairline border, which read as
   DISABLED — the one control on the panel you are meant to type in looked switched
   off — while the send button was a large pill floating beside it at a different
   radius and height. Now: a white field on a light ground, both controls the same
   height and radius, aligned as one input group. */
/* Formatting bar. Sits on the same white ground as the composer and reads as
   part of it — a separated strip would look like another section of the panel. */
.odr-wa-toolbar { flex:0 0 auto; display:flex; align-items:center; gap:4px;
    padding:10px 16px 0; background:var(--re-dash-bg); border-top:1px solid var(--re-dash-border); }
.odr-wa-fmt { appearance:none; background:none; border:1px solid transparent;
    border-radius:6px; width:28px; height:28px; padding:0; cursor:pointer;
    font-size:12px; line-height:1; color:#5b6770;
    transition:background .12s ease, color .12s ease, border-color .12s ease; }
.odr-wa-fmt:hover { background:#eef2f4; color:#1f2530; }
.odr-wa-fmt:focus-visible { outline:0; border-color:var(--re-dash-brand); box-shadow:0 0 0 3px rgba(12,189,24,.14); }
.odr-wa-fmt code { background:none; border:0; padding:0; font-size:11px; color:inherit; }
.odr-wa-toolbar-hint { margin-left:auto; font-size:11px; color:#98a4ad; white-space:nowrap; }

.odr-wa-compose { flex:0 0 auto; display:flex; align-items:flex-end; gap:10px;
    padding:10px 16px 16px; background:var(--re-dash-bg); }
.odr-wa-chat-input { flex:1 1 auto; resize:none; min-height:42px; max-height:132px;
    padding:11px 14px; font-size:13.5px; line-height:1.45; color:var(--re-dash-fg);
    background:var(--re-dash-bg); border:1px solid #d3dae0; border-radius:10px;
    box-shadow:inset 0 1px 2px rgba(17,24,28,.04);
    transition:border-color .15s ease, box-shadow .15s ease; }
.odr-wa-chat-input::placeholder { color:#98a4ad; }
.odr-wa-chat-input:hover { border-color:#b9c3cb; }
.odr-wa-chat-input:focus { outline:0; border-color:var(--re-dash-brand);
    box-shadow:0 0 0 3px rgba(12,189,24,.14); }
/* Matches the field's height and radius so the pair reads as one control, not a
   textarea with a button parked next to it. */
.odr-wa-chat-send { flex:0 0 auto; appearance:none; border:0; border-radius:10px;
    height:42px; padding:0 20px; font-size:13.5px; font-weight:600; letter-spacing:.01em;
    color:var(--re-dash-bg); background:var(--re-dash-brand); cursor:pointer; white-space:nowrap;
    box-shadow:0 1px 2px rgba(10,143,20,.25);
    transition:background .15s ease, box-shadow .15s ease, transform .05s ease; }
.odr-wa-chat-send:hover:not(:disabled) { background:#0aa515; box-shadow:0 2px 6px rgba(10,143,20,.3); }
.odr-wa-chat-send:active:not(:disabled) { transform:translateY(1px); }
.odr-wa-chat-send:disabled { opacity:.5; cursor:default; box-shadow:none; }
.odr-wa-chat-send:focus-visible { outline:2px solid #0a7d12; outline-offset:2px; }
.odr-wa-chat-error { padding:0 16px 10px; background:var(--re-dash-bg); }

.odr-wa-lazy { padding:24px 4px; font-size:13px; color:var(--re-dash-fg-muted); }

/* Recipient reminder above the template form — the old popup never said who it
   was about to message. */
.odr-wa-tmpl-to { margin:0 0 12px; padding:8px 11px; font-size:12px;
    background:rgba(12,189,24,.07); border-left:3px solid var(--re-dash-brand); border-radius:0 4px 4px 0; }
.odr-wa-tmpl-to strong { font-weight:700; }

.odr-wa-sr { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0);
    white-space:nowrap; }

/* Narrow drawers (the panel is clamp(340px,46vw,760px)) */
@media (max-width:600px) {
    .odr-wa-bubble { max-width:88%; }
    .odr-wa-ctx { flex-wrap:wrap; }
}

@media (prefers-reduced-motion:reduce) {
    .odr-wa-scroll { scroll-behavior:auto; }
    .odr-wa-meter-bar > span { transition:none; }
}

/* Template preview SLOT — a fixed viewport, deliberately not content-sized.
   The one-click quick links sit directly BELOW this box and fire a real WhatsApp
   on a single click, while the preview renders on hover/focus of those same
   links. Letting the box grow to its message meant every hover pushed the row of
   links down by the height of the preview, moving the next link out from under a
   pointer that was already travelling towards it — on controls where a stray
   click sends a message to a customer. So the slot claims its space up front and
   scrolls internally: the preview changes, the layout below never does.

   Sized to clear a typical template body PLUS the top of the unresolved-
   placeholder alert (the 131008 guard), so the warning is not something you
   only find by scrolling. */
/* min-height, not height. A fixed 180px box meant every template longer than the
   box had to be scrolled INSIDE it to be read — you cannot check a message you can
   only see half of, which defeats the point of a preview. It now grows to fit.
   The reserved minimum stays, because that is what stops the empty state
   collapsing; and the quick-link chips now sit ABOVE the select, so the preview
   growing underneath no longer shifts the controls out from under the pointer —
   which was the original reason the height was pinned. */
.odr-wa-preview-box { min-height:180px; overflow-x:hidden; }
.odr-wa-preview-box:empty { border:1px dashed #d9e0e6; border-radius:6px; }
.odr-wa-preview-box:empty::before {
    content:"Pick a template above, or hover a quick link below, to preview the exact message.";
    display:block; padding:12px 13px; font-size:12px; line-height:1.45; color:#8a93a0; }

/* Template preview bubble — same outbound treatment as a real thread bubble, so the
   "exactly what will be sent" claim looks like what the customer will actually get.
   (Was an inline #dcf8c6 style hardcoded in odr_wa_preview_html().) */
.odr-wa-preview-bubble { max-width:100%; padding:10px 13px; font-size:13px; line-height:1.45;
    color:#1f2430; background:#e7f7e8; border:1px solid #cdead0; border-radius:12px 3px 12px 12px;
    word-break:break-word; }
.odr-wa-preview-bubble a { color:#0a6ebd; text-decoration:underline; }
.odr-wa-preview-bubble code { background:rgba(17,21,30,.06); padding:0 3px; border-radius:3px; font-size:12px; }

/* ── Projects table inside the right slide-in ─────────────────────────────
   The panel is much narrower than the dashboard, and this table has five
   columns plus a full-width file-name row. Two things were clipping it:

   1. Nothing constrained the table, so Status and Dated were simply cut off
      at the panel edge with no way to scroll to them.
   2. Uploaded file names have no spaces — "KaMLESH_Role-of-Financial-
      Inclusion-in-Women-Empowerment_5th-May.docx" cannot wrap, so it set a
      minimum width and pushed the columns out of view.

   The wrapper scrolls rather than clips; the file name is allowed to break
   anywhere so it stops dictating the table's width in the first place. */
.modal-data-table-wrap {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* Lets the table respond to the PANEL's width rather than the viewport's. The
       slide-in is clamp(340px,46vw,760px), so a viewport media query would be
       measuring the wrong box entirely. */
    container-type: inline-size;
}

.modal-data-table {
    width: 100%;
    table-layout: auto;
}

/* The old rule here pinned the FIRST column to width:1%/nowrap, because the first
   column used to be S.No. That column is gone; the first cell now carries the
   project id, status and action icons, and must be allowed to breathe. */
.modal-data-table th:first-child,
.modal-data-table td:first-child {
    width: 34%;
}

.modal-data-status {
    font-size: 11px;
    text-transform: capitalize;
}

/* Below this width three columns stop being readable — cells get so narrow that
   every value wraps to three lines and the row is taller than a stacked card would
   be. So stack: each row becomes a block, each cell a labelled line.

   Container query, not a media query: what matters is how wide the PANEL is, and the
   same table also renders in a full-width page where it should stay a table. */
@container (max-width: 520px) {
    .modal-data-table,
    .modal-data-table tbody,
    .modal-data-table tr,
    .modal-data-table td {
        display: block;
        width: 100%;
    }

    /* The header row has nowhere to go once cells are stacked — each cell carries its
       own label instead (data-label, set in action_get_user_projects_html). */
    .modal-data-table tr:first-child th {
        display: none;
    }

    .modal-data-table tr {
        border: 1px solid #e3e6ea;
        border-radius: 8px;
        margin-bottom: 10px;
        padding: 8px 10px;
    }

    /* The filename/remarks row is a continuation of the project above it, not a card
       of its own — join it visually to the row it belongs to. */
    .modal-data-table tr.modal-data-subrow {
        border-top: 0;
        border-radius: 0 0 8px 8px;
        margin-top: -11px;
        margin-bottom: 10px;
    }

    .modal-data-table td {
        border: 0;
        padding: 3px 0;
    }

    .modal-data-table td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: 10px;
        letter-spacing: .04em;
        text-transform: uppercase;
        color: #8a9099;
        margin-bottom: 1px;
    }

    /* Nothing to label on the continuation row. */
    .modal-data-table tr.modal-data-subrow td::before {
        content: none;
    }
}

/* The offender: break a long unspaced file name instead of widening the table.
   The DISPLAY length is handled server-side now by rel_truncate_file_name() (first
   15 chars + extension, full name in its title) — the shared dashboard treatment, so
   these names read the same here as everywhere else. This rule stays as the backstop
   for the file_status suffix appended after the truncated name. */
.modal-data-filename {
    overflow-wrap: anywhere;
    word-break: break-word;
    max-width: 100%;
}

/* Project id / service / status read better unwrapped, but must not force
   the panel wider than it is — they can wrap once the file name no longer
   pins the layout. */
.modal-data-table td,
.modal-data-table th {
    overflow-wrap: anywhere;
    vertical-align: top;
}

/* ---------------------------------------------------------------------------
   Screen-help panel body.

   The panel rendered its <ul>/<li> with no markers and no separation, so every
   list item read as an indented paragraph and four distinct issue types looked
   like one long run of prose — the content was right, the shape carried none of
   it. These give the lists back their structure: a marker per item, air between
   items, and headings that group rather than float.
   --------------------------------------------------------------------------- */
.rel-screen-help__intro { margin-bottom: 1.1rem; line-height: 1.6; }

.rel-screen-help__body h6,
.rel-screen-help h6 { margin-top: 1.5rem; margin-bottom: .5rem; font-weight: 700; }

.rel-screen-help__body ul {
    margin: 0 0 .35rem;
    padding-left: 1.15rem;
    list-style: disc outside;
}

.rel-screen-help__body li {
    margin-bottom: .5rem;
    line-height: 1.55;
    padding-left: .15rem;
}
.rel-screen-help__body li:last-child { margin-bottom: 0; }

/* The bolded term that opens most items is the scannable part — let it breathe
   from the explanation that follows it. */
.rel-screen-help__body li strong { margin-right: .1rem; }

.rel-screen-help__body code {
    padding: .1rem .3rem;
    border-radius: 3px;
    background: #f3f5f7;
    color: #b0407a;
    font-size: .92em;
}

/* ===================== Referral card (.odr-refer) =====================
   Replaces an animated four-colour gradient that looped every 6 seconds and
   carried seven inline styles plus a global .btn-light override emitted from
   inside a PHP function. Calm on purpose: this sits on the customer's own
   dashboard next to their projects, and it is an offer, not a promotion.
   Tokens are redeclared locally because the customer dashboard carries none
   of the .odr-* page wrappers that declare them. */

.odr-refer{border:1px solid var(--re-dash-border);border-radius:12px;box-shadow:0 1px 2px rgba(16,38,48,.04),0 14px 34px -24px rgba(16,38,48,.22);}
.odr-refer .card-body{padding:26px 28px;}
.odr-refer-title{font-family:'Quicksand',sans-serif;font-weight:700;font-size:19px;color:var(--re-dash-fg);margin:0 0 8px;}
.odr-refer-lede{font-family:'Open Sans',sans-serif;font-size:13.5px;line-height:1.65;color:var(--re-dash-fg-secondary);max-width:60ch;margin:0 0 18px;}
.odr-refer-link{display:flex;flex-direction:column;gap:3px;background:var(--re-dash-success-soft);border:1px solid #d6ecd4;border-radius:8px;padding:11px 14px;margin-bottom:18px;}
.odr-refer-link-label{font-family:'Open Sans',sans-serif;text-transform:uppercase;font-size:10px;letter-spacing:.07em;color:var(--re-dash-fg-muted);font-weight:700;}
.odr-refer-link a{font-family:'Open Sans',sans-serif;font-size:13px;color:var(--re-dash-success-dark);font-weight:600;overflow-wrap:anywhere;}
.odr-refer-actions{display:flex;flex-wrap:wrap;gap:10px;}
.odr-refer-actions .btn{font-family:'Open Sans',sans-serif;font-weight:700;font-size:13px;border-radius:8px;padding:9px 18px;text-transform:none;}
.odr-refer-actions .btn-success{background:var(--re-dash-success);border-color:var(--re-dash-success);color:var(--re-dash-bg);}
.odr-refer-actions .btn-success:hover{background:var(--re-dash-success-dark);border-color:var(--re-dash-success-dark);}
.odr-refer-actions .btn-outline-secondary{color:var(--re-dash-fg-secondary);border-color:var(--re-dash-border);background:var(--re-dash-bg);}
.odr-refer-actions .btn-outline-secondary:hover{border-color:#cfd8e0;color:var(--re-dash-fg);}
.odr-refer-note{font-family:'Open Sans',sans-serif;font-size:12.5px;line-height:1.6;color:var(--re-dash-fg-muted);margin:18px 0 0;}
.odr-refer-note strong{color:var(--re-dash-fg-secondary);}
@media (max-width:576px){.odr-refer .card-body{padding:20px;}.odr-refer-actions .btn{flex:1 1 100%;text-align:center;}}

/* ===================== Filter panel — type scale =====================
   The panel had one size and one shade for everything: 40+ checkbox labels,
   the group labels and the section headings all landed at ~15-16px near-black,
   so nothing led the eye and a tidy panel still read as noise.

   Three levels, using tokens that already exist — no new colours:
     section heading   13px semibold, --re-dash-fg          ("Lead Status Filters")
     group label       11px uppercase, --re-dash-fg-muted   ("User Lead Status")
     option label      12.5px,         --re-dash-fg-secondary (the checkboxes)

   Scoped to .rel-dt-filters so it cannot leak into forms or modals.
   ==================================================================== */

/* Section heading — the one real heading in the panel. */
.pcoded-content .rel-dt-filters [data-toggle="collapse"] h6 {
  font-size: 13px;
  font-weight: 600;
  color: var(--re-dash-fg);
  letter-spacing: 0;
}

/* Group label — a label for the set beneath it, not a heading. */
.pcoded-content .rel-dt-filters .collapse .row > [class*="col-"] > h6 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--re-dash-fg-muted);
  margin-bottom: 10px;
}

/* Option labels — the checkbox/radio text. Quietest level: there are dozens of
   them and they are scanned, not read. */
.pcoded-content .rel-dt-filters .form-check-label {
  font-size: 12.5px;
  color: var(--re-dash-fg-secondary);
  line-height: 1.5;
}

/* The checked one earns the darker shade. */
.pcoded-content .rel-dt-filters .form-check-input:checked ~ .form-check-label {
  color: var(--re-dash-fg);
  font-weight: 600;
}

/* Clear button sits with the options, so it matches them rather than shouting. */
.pcoded-content .rel-dt-filters .clear-checkboxes {
  font-size: 11px;
  color: var(--re-dash-fg-muted);
}

/* Filter action row — one height for every button.
   "Auto Refresh" wraps a number input, and a browser-default number input is
   ~20px tall against a 13.75px text line, so that one button rendered 6px
   taller than Reset/Excel/GST beside it. Fixing the row height and centring
   the contents means an inner control aligns instead of stretching its button. */
.pcoded-content .rel-dt-filters .btn,
.pcoded-content .re-dt-filter-actions .btn {
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

/* ====================================================================
   THE filter panel. One definition, every screen.

   The panel was never a style — it was two templates (filters-default and
   filters-users) wrapping their fields in `border rounded bg-light py-4` by
   hand. The other ten filter templates — Approvals, Project Issues,
   Publications, Projects, Leads, Publishing List, the activity views — wrapped
   theirs in nothing, so those screens rendered bare controls on the page
   background while Users looked finished. Same complaint as the token debt
   noted in CLAUDE.md: a look that lives in a hardcoded list of screens instead
   of in the class every screen already shares.

   So it lives here, on .rel-dt-filters, which all twelve templates carry. The
   two templates that hand-rolled a box have had it removed rather than left to
   draw a second border inside this one.
   ==================================================================== */
.pcoded-content .rel-dt-filters {
  background: var(--re-dash-bg-header);
  border: 1px solid var(--re-dash-border);
  border-radius: var(--re-dash-control-radius);
  padding: 1.25rem 1.5rem;
  /* Clear of the Search Filters handle and the Refresh/Reset/Excel row above,
     which sat directly on the panel's top border. */
  margin-top: .5rem;
}

/* And room between the panel and what follows it — the Show/entries row used to
   start 8px under the border. */
.pcoded-content .rel-dt-containers {
  margin-bottom: 1rem;
}

/* ====================================================================
   Project action panel — the slide-in behind the row's nine icons.

   Actions read as a LIST, not a grid of glyphs: icon, name, and one line
   saying what it does. These are the controls people reach for least often,
   which is exactly when a label earns its space. The destructive group is
   separated by rule and colour rather than sitting inline with edit.
   ==================================================================== */
.odr-pp-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  border-bottom: 1px solid var(--re-dash-border);
  margin-bottom: 14px;
}

.odr-pp-tab {
  background: none;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: 6px 6px 0 0;
  padding: 7px 14px;
  font-size: 13px;
  color: var(--re-dash-fg-secondary);
  cursor: pointer;
}

.odr-pp-tab.is-active {
  background: var(--re-dash-bg-header);
  border-color: var(--re-dash-border);
  color: var(--re-dash-fg);
  font-weight: 600;
}

/* The jump to the other drawer. Sits in the tab bar but is not a tab — it opens a
   panel rather than switching a pane, so it reads as a link, not a state. */
.odr-pp-tab--jump {
  margin-left: auto;
  color: var(--re-dash-brand);
  border-color: transparent;
}

.odr-pp-tab--jump:hover { text-decoration: underline; }

.odr-pp-pane { display: none; }
.odr-pp-pane.is-active { display: block; }

.odr-pp-pane__blurb,
.odr-pp-group__blurb {
  font-size: 12.5px;
  color: var(--re-dash-fg-muted);
  margin: 0 0 12px;
}

.odr-pp-group { margin-bottom: 22px; }

.odr-pp-group__title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--re-dash-fg-muted);
  margin: 0 0 2px;
}

.odr-pp-group__blurb { margin-bottom: 8px; }

.odr-pp-actions { display: flex; flex-direction: column; gap: 6px; }


.odr-pp-action {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--re-dash-border);
  border-radius: 8px;
  background: var(--re-dash-bg);
  cursor: pointer;
}

.odr-pp-action:hover { background: var(--re-dash-bg-row-hover); }
.odr-pp-action:focus-visible { outline: 2px solid var(--re-dash-brand); outline-offset: 2px; }

.odr-pp-action__icon { width: 20px; text-align: center; padding-top: 2px; }

/* align-items keeps the count badge to its own width — in a flex COLUMN it
   stretches to the full row otherwise, and "1" renders as a blue bar. */
.odr-pp-action__text { display: flex; flex-direction: column; align-items: flex-start; }
.odr-pp-action__name { display: flex; align-items: center; gap: 7px; }
.odr-pp-action__text b { font-size: 13.5px; font-weight: 600; color: var(--re-dash-fg); }
.odr-pp-action__text span { font-size: 12.5px; color: var(--re-dash-fg-muted); }

/* The group you should have to mean. */
.odr-pp-group--danger { border-top: 2px dashed var(--re-dash-danger); padding-top: 14px; }
.odr-pp-action--danger { border-color: var(--re-dash-danger); background: var(--re-dash-danger-soft); }
.odr-pp-action--danger .odr-pp-action__text b { color: var(--re-dash-danger); }

/* Count badge (e.g. "Project files 1") — Bootstrap's own .badge-primary text
   colour read as low-contrast on its blue background here. Forced to the
   design system's inverse token rather than a raw hex. */
.odr-pp-action__name .badge-primary { color: var(--re-dash-fg-inverse); }

/* Each icon-strip (contact channels, then panel tabs) on its own visible
   line. The tiles (.icon-card) are inline <span>s whose big padding doesn't
   grow the line box, so when a strip wrapped, its second line overlapped the
   first. Flex makes each tile a real box and the gap owns ALL spacing —
   which is also why the 'card' variant emits no mr-3 (a Bootstrap
   !important margin would stack on the gap unevenly). */
.odr-pp-triggers-row { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 14px; }
.odr-pp-triggers-row:last-child { margin-bottom: 0; }
/* The strips' own root <span> wrappers must not swallow the tiles into one
   flex item — dissolve them so every tile sits on the row grid directly. */
.odr-pp-triggers-row .odr-contact-actions,
.odr-pp-triggers-row .odr-project-actions { display: contents; }
.odr-pp-triggers-row .icon-card {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin: 0; /* .icon-card ships margin-bottom:15px; the row gap replaces it */
}

/* Project schedule widget (odr_project_schedule_html) — who holds the project,
   when it is due, what has happened to it. Three grouped lines replacing five
   stacked "Label: value" rows of identical weight, where the only thing anyone
   scans for is the delivery date. Sized to match the customer card beside it. */
.pcoded-content .re-proj-sched {
  margin-top: 6px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--re-dash-fg-secondary);
}

/* The one date with a promise attached to it. */
.pcoded-content .re-proj-sched .re-proj-sched__due {
  color: var(--re-dash-danger);
  font-weight: 600;
}

/* Vendor & Expenses reporting tab — the tile figure and the chart boxes, which
   were carrying a hardcoded #0cbd18 and inline heights in the template. */
.odr-vendor-expenses .ve-stat-brand { color: var(--re-dash-brand); }
.odr-vendor-expenses .ve-chart      { position: relative; height: 300px; }
.odr-vendor-expenses .ve-chart-sm   { height: 220px; }

/* Reporting date range (quick-task #33). Borrows the shape of the re-dashboard date
   bar so the two screens read the same, using tokens rather than that screen's
   hardcoded greys. */
.odr-vendor-expenses .ve-report-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--re-dash-bg-header);
  border: 1px solid var(--re-dash-border);
  border-radius: 4px;
}
.odr-vendor-expenses .ve-rpt-datepicker {
  flex: 0 0 auto;
  white-space: nowrap;
  cursor: pointer;
  background: var(--re-dash-bg);
  border: 1px solid var(--re-dash-border);
  border-radius: 4px;
  padding: 5px 10px;
  font-size: .85rem;
}
.odr-vendor-expenses .ve-rpt-note { color: var(--re-dash-fg-muted); font-size: 12px; }
/* Marks a figure whose scope is the chosen range rather than all time, so a reader
   cannot mistake it for a lifetime total sitting next to a filtered one. */
.odr-vendor-expenses .ve-rpt-scoped {
  color: var(--re-dash-info-dark);
  font-weight: 600;
}

/* The seconds box: sized to its three digits, borrowing the panel's border. */
.pcoded-content .auto-refresh {
  height: 20px;
  width: 40px;
  padding: 0 4px;
  border: 1px solid var(--re-dash-border);
  border-radius: 4px;
  font-size: 11.5px;
  line-height: 1;
  text-align: center;
  background: var(--re-dash-bg);
  color: var(--re-dash-fg-secondary);
}

/* Customer summary widget — one card, three lines.
   Used by Projects, My Leads, Users, Leads and Project Issues via
   odr_customer_summary_html(). Before this, My Leads and Projects each built
   their own version and formatted money differently, so the same customer's
   lifetime value read "Rs 56,945.00" on one screen and "INR 56,945" on the
   other. Sizing follows the My Leads meta line, which was the readable one. */
.pcoded-content .re-cust-summary {
  border: 1px solid var(--re-dash-border);
  border-radius: 8px;
  padding: 8px 12px;
  background: var(--re-dash-bg);
  position: relative; /* anchors the top-right quick actions */
}

/* Collapsed-by-default toggle (owner, 2026-08-23): body and reveal line
   both always render — the toggle is a pure CSS/JS class flip, not a
   re-fetch, so the click in ajaxactions.js is instant on every card
   already on the page. --hidden is the state class re_get_cookie()
   decides server-side on first paint; the class flip on click is what
   keeps subsequent clicks from waiting on a server round trip. */
.pcoded-content .re-cust-summary__reveal {
  display: none;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--re-dash-fg-muted);
}
.pcoded-content .re-cust-summary--hidden .re-cust-summary__reveal {
  display: inline-block;
}
.pcoded-content .re-cust-summary--hidden .re-cust-summary__body {
  display: none;
}

/* Lead status/offer + fee-summary box (get_column_html() 'service' case,
   trait-project-dt.php) ride the SAME cookie/toggle as the card above —
   no chrome or reveal line of its own, just hidden or not. */
.pcoded-content .re-cust-toggle--hidden {
  display: none;
}

/* Edit-user + user-actions slide-in triggers, top-right of the card
   (owner, 2026-08-14) — same two entries the user-details page offers. */
.pcoded-content .re-cust-summary .re-cust-summary__actions {
  position: absolute;
  top: 6px;
  right: 8px;
}

/* Smaller than the 28px strip buttons — inside the card they are corner
   accessories, not primary actions (owner, 2026-08-14). */
.pcoded-content .re-cust-summary .re-cust-summary__actions .re-dash-icon-sq {
  width: 22px;
  height: 22px;
  font-size: 11px;
  border-radius: 5px;
}
.pcoded-content .re-cust-summary .re-cust-summary__actions .re-dash-icon-sq.mr-2 {
  margin-right: 4px !important; /* Bootstrap's .mr-2 (8px) is oversized at this scale */
}

/* One measure for every line (v2 won the compare round, 2026-08-14): 12.5px,
   one rhythm, and a 5px bottom margin — the owner's own fix so pills on
   consecutive lines don't touch. */
.pcoded-content .re-cust-summary__body > span {
  font-size: 12.5px;
  line-height: 1.7;
  margin: 0 0 5px;
  color: var(--re-dash-fg-secondary);
}

/* Labels are labels, not shouts: strongs sit at normal weight in full ink.
   The ban line is the one exception below — red + bold is its alarm job. */
.pcoded-content .re-cust-summary strong {
  color: var(--re-dash-fg);
  font-weight: 400;
}
.pcoded-content .re-cust-summary .re-text-danger strong {
  font-weight: 600;
}

/* Importance pills (odr_cust_pill + the open WhatsApp-window badge): the pill
   IS the highlight, so the text inside stays normal weight and compact
   (owner-specified sizing, 2026-08-14). */
.pcoded-content .re-cust-summary .badge-lg {
  font-weight: 400;
  font-size: 11px;
  padding: 3px 5px;
}

/* Leading line icon (odr_customer_summary_html()) — fixed-width slot so
   every line's text starts at the same x-offset regardless of which glyph
   is in it (a wallet and a location pin are not the same width), and a colour
   pulled from the SAME token the line text already uses (--re-dash-fg-muted,
   a blue-slate grey) instead of Bootstrap's neutral .text-muted, which read
   as a mismatched grey against the page's own blue-grey background family. */
.pcoded-content .re-cust-summary .re-cust-icon {
  display: inline-block;
  width: 16px;
  margin-right: 8px;
  text-align: center;
  color: var(--re-dash-fg-muted);
}

/* re-cust-tier1 retired entirely (owner, 2026-08-14) — every line sits on the
   same measure and ink; pills and the deviation flag are the only emphasis. */

/* PM on the heading — plain text, hyphen-separated (owner final round). */
.pcoded-content .re-cust-summary .re-cust-pm {
  font-size: 12.5px;
  font-weight: 400;
  color: var(--re-dash-fg);
  text-transform: none;
  letter-spacing: normal;
}

/* Every anchor on the card sits on the card's own measure — template default
   link sizing (14px) stuck out on the Last Project id. */
.pcoded-content .re-cust-summary a {
  font-size: 12.5px;
}

/* Details-page footnote: a whisper, not a line item — no icon slot, lightest
   ink, a hair of space above. */
.pcoded-content .re-cust-summary .re-cust-hover-note {
  font-size: 10.5px;
  color: var(--re-dash-fg-placeholder);
  text-align: right;
  margin: 2px 0 -6px; /* pulls into the card's 8px bottom padding — flush with the edge */
}

/* Deviation treatment (owner, 2026-08-14): lines/bits that render ONLY when
   something is off-default — preferences, "Source unknown", "WhatsApp
   unconfirmed", empty-but-should-be-set gaps. Same size as every line, but
   weight-600 in full ink: rarity earns the eye, without a badge. Applies in
   BOTH compare cards — it is a semantics decision, not a v2 look. */
.pcoded-content .re-cust-summary .re-cust-flag,
.pcoded-content .re-cust-summary .odr-u-gap {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--re-dash-fg);
}

/* Project details header file line + view links (2026-08-14 reorder).
   The file line takes the old User View chip's slot; the view links join the
   action strip as bare glyphs — black ink, not the tab-blue, so "go somewhere
   else" reads differently from "open a panel here". */
/* AutoPc triple (owner, 2026-08-14 — the old inline run of mixed baselines
   was, in their words, laughable): three equal cells, a quiet mini-label
   above each value, everything on one baseline. */
.odr-pp-triple { gap: 12px; }
.odr-pp-triple .odr-pp-mini-label {
  display: block;
  font-size: 10.5px;
  color: var(--re-dash-fg-muted);
  line-height: 1.2;
}

/* Title-row copy icons (project id + customer name): hover-revealed and cut
   down to a modest glyph — they were inheriting the h5's scale. */
.page-header .page-header-title .copy-container .copy-icon {
  font-size: 14px;
  vertical-align: middle;
}

.odr-pp-file-line {
  display: block;
  font-size: 12.5px;
  color: var(--re-dash-fg-secondary);
  margin-top: 4px;      /* same breath the title row keeps from the icon above */
  line-height: 1.5;
}
.odr-pp-file-line a { font-size: 12.5px; }
.odr-pp-file-line .label-danger { vertical-align: middle; margin-left: 4px; }
/* View links (owner, 2026-08-14): the USER view eye is blue everywhere —
   matching the search card's — and the EDITOR view stays black ink. */
.odr-pp-triggers-row .odr-pp-view-link--user,
.odr-pp-triggers-row .odr-pp-view-link--user i { color: var(--re-dash-info); }
.odr-pp-triggers-row .odr-pp-view-link--editor,
.odr-pp-triggers-row .odr-pp-view-link--editor i { color: var(--re-dash-fg); }
.odr-pp-triggers-row .odr-pp-view-link:hover i { color: var(--re-dash-brand-dark); }

/* A dialog is always the top-most thing on screen.
   SweetAlert2 ships z-index:1060; the slide-in panel (.rel-si-root, :674) sits
   at 1090, so a confirm opened FROM a slide-in — "Assign Project To Counsellor"
   on the My Leads edit panel, for one — rendered BEHIND the panel: greyed,
   half-covered, and competing with the form it was asking about. */
.swal2-container { z-index: 1100; }

/* ── Project card v2 (concept B, functional) ──
   Document-header hero + field-cluster grid; every value is the live
   editable_columns() span, so cells stay clickable-to-edit. */
.odr-ppv2-card .card-block { padding: 18px 20px; }
.odr-ppv2-hero { display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--re-dash-border-light); }
.odr-ppv2-service { font-size: 1.25rem; font-weight: 600; color: var(--re-dash-fg); }
.odr-ppv2-service .rel-editable { display: inline-block; }
.odr-ppv2-chips { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.odr-ppv2-chip { font-size: 11px; padding: 3px 8px; border-radius: 10px; display: inline-flex;
  align-items: center; gap: 3px;
  background: var(--re-dash-bg-row-hover); color: var(--re-dash-fg-secondary); }
.odr-ppv2-chip .rel-editable { display: inline-block; }
.odr-ppv2-hero-right { text-align: right; }
/* Status chip now renders as .odr-pill directly (functions-html.php's map) —
   no separate odr-ppv2-status shape/colour needed, dropped 2026-08-20. */
.odr-ppv2-cell--danger { background: var(--re-dash-danger-soft); border-color: var(--re-dash-danger); }
.odr-ppv2-advanced { display: none; } /* toggle-slide-handle slides it open */
.odr-ppv2-advanced .odr-ppv2-eyebrow { color: var(--re-dash-danger); }
/* Legacy table card ships collapsed — the header minimize control reopens it. */
.odr-pp-legacy-collapsed .card-block { display: none; }
.odr-ppv2-when { display: block; margin-top: 5px; font-size: 10.5px; color: var(--re-dash-fg-muted); }
.odr-ppv2-eyebrow { font-size: 10px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--re-dash-fg-muted); margin: 14px 0 6px; }
.odr-ppv2-grid { display: grid; gap: 8px; }
.odr-ppv2-grid--2 { grid-template-columns: repeat(2, 1fr); }
.odr-ppv2-grid--3 { grid-template-columns: repeat(3, 1fr); }
.odr-ppv2-grid--4 { grid-template-columns: repeat(4, 1fr); }
.odr-ppv2-cell { background: var(--re-dash-bg); border: 1px solid var(--re-dash-border-light);
  border-radius: 6px; padding: 7px 10px; font-size: 12.5px; color: var(--re-dash-fg);
  min-width: 0; /* grid children may otherwise refuse to shrink */ }
.odr-ppv2-lbl { display: block; font-size: 10.5px; color: var(--re-dash-fg-muted); line-height: 1.3; }
/* Measurements block. Every other cell on this card is click-to-edit; these are
   deliberately not (single write path for anything that moves the fee — see the
   comment in view-projects-details.php), so the eyebrow carries a quiet note
   rather than leaving the reader to discover it by clicking. */
.odr-ppv2-eyebrow-note { font-weight: 500; letter-spacing: 0; text-transform: none;
  color: var(--re-dash-fg-placeholder); }
.odr-ppv2-hint { color: var(--re-dash-fg-placeholder); }
/* Matches the height and rhythm of an editable cell's value so the block sits
   flush with the grids above and below it. */
.odr-ppv2-ro { display: block; padding: 2px 0; color: var(--re-dash-fg); }
.odr-ppv2-panel { border: 1px solid var(--re-dash-border-light); border-radius: 6px;
  padding: 8px 10px; font-size: 12.5px; color: var(--re-dash-fg); margin-bottom: 6px;
  background: var(--re-dash-info-soft); }
.odr-ppv2-panel--warn { background: var(--re-dash-warning-soft); }

/* Editor's "Customer Update" strip (functions-ajax-team-actions.php): a quiet
   ppv2 panel — note left, window badge + mini dotted CTA right. The dotted
   outline is the owner's spec for this button; colour comes from the success
   tokens, never a hex. Wraps on narrow cards instead of overflowing. */
.odr-wa-update { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; background: var(--re-dash-bg); }
.odr-wa-update__text { min-width: 220px; flex: 1 1 260px; }
.odr-wa-update__hint { display: block; font-size: 11px; color: var(--re-dash-fg-muted); margin-top: 2px; }
.odr-wa-update__last { color: var(--re-dash-fg-placeholder); }
.odr-wa-update__cta { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.odr-wa-update__btn { border: 1px dotted var(--re-dash-success-dark); color: var(--re-dash-success-dark);
  background: transparent; border-radius: var(--re-dash-control-radius); font-weight: 600; }
.odr-wa-update__btn:hover, .odr-wa-update__btn:focus { background: var(--re-dash-success-soft);
  color: var(--re-dash-success-dark); border-style: solid; }
.odr-ppv2-files .table td, .odr-ppv2-files .table th {
  border-top: 0; border-bottom: 1px solid var(--re-dash-border-light);
  font-size: 12.5px; padding: 7px 10px; }
.odr-ppv2-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 16px; }
/* select2 (searchable) inside a cell must fill the cell, and its dropdown
   overlays the grid rather than stretching it. */
.odr-ppv2-cell .select2-container { width: 100% !important; /* select2 inlines its own width */ }
@media (max-width: 992px) {
  .odr-ppv2-grid--3, .odr-ppv2-grid--4 { grid-template-columns: repeat(2, 1fr); }
}

/* v2 card link icons — neutral ink (owner: text-default, blue was loud). */
.odr-ppv2-cell .odr-ppv2-linkicon { color: var(--re-dash-fg-secondary); }
.odr-ppv2-cell .odr-ppv2-linkicon:hover { color: var(--re-dash-fg); }

/* Empty editable placeholders inside the v2 card — an invitation, not an
   alarm (owner: red is too much). */
.odr-ppv2-card .rel-editable-value.no-value,
.odr-ppv2-card .rel-editable-value.no-value a { color: var(--re-dash-fg-placeholder); }

/* File-row actions as the shared square icons, light ink until hover. */
.odr-ppv2-files .re-dash-icon-sq--file {
  width: 24px;
  height: 24px;
  font-size: 11px;
  color: var(--re-dash-fg-placeholder);
}
.odr-ppv2-files .re-dash-icon-sq--file:hover { color: var(--re-dash-fg); }
.odr-ppv2-files .re-dash-icon-sq--file small { font-size: 8px; margin-left: 1px; }

/* User card v2 — same cell-grid language; the ban panel is the one loud thing. */
.odr-ucv2-ban { background: var(--re-dash-danger-soft); color: var(--re-dash-danger); }
.odr-ppv2-empty { color: var(--re-dash-fg-placeholder); }

/* Added 2026-08-20 for the editor screen — the v2 system had no workflow-
   action or upload-form primitives yet. Layout/spacing only. Colour used to
   come from an ID-scoped #main-project-body override (removed 2026-08-21 —
   it flattened every button, including btn-success/-warning/-danger, to the
   same black outline regardless of what class was on it; an ID selector beats
   any number of classes, so nothing without an ID of its own could override
   it back). Buttons here now carry real Bootstrap variant classes directly
   (btn-success/-warning/-danger/-info/-outline-dark) instead. */
.odr-ppv2-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.odr-ppv2-actions .btn { flex: 1 1 auto; }
.odr-ppv2-upload { border: 1px solid var(--re-dash-border-light); border-radius: 6px; padding: 4px; }

/* Copy-container cursor, the rule that actually WINS: the source fix in
   omak-dash/style-admin-override.css is compiled into minified/styles.min.css
   and stays stale until the next webpack build — so the correction lives here
   too. Only the icon promises a click.
 *
 * Scoped to `body`, NOT `.pcoded-content`. The earlier `.pcoded-content` version
 * missed everything rendered outside the content area — the global-search
 * results, the RelSlide drawers and the notes drawer are all appended to <body>,
 * so their cards kept the pointer over the whole text (project id, customer
 * name, file names) while the same helper behaved correctly in the datatables.
 *
 * A bare `.copy-container` would be the tidy answer but LOSES: re-dash's
 * style.css is enqueued from the rel_dequeue_scripts hook, which omak-dash fires
 * at functions-theme.php:240 — three lines BEFORE it enqueues styles.min.css. On
 * equal specificity the later sheet wins, so one extra selector is required. */
body .copy-container { cursor: default; }
body .copy-container .copy-icon,
body .copy-container .copy-icon-show-always { cursor: pointer; }

/* ============================================================
   CHAT LAUNCHER — dashboard bubble (WhatsApp / live chat / Jimmy)
   Markup: includes/functions-chat-launcher.php · behaviour:
   theme/admin/js/my-account.js. Same component as the public
   launcher in re-theme, re-expressed in --re-dash-* tokens
   because the theme stylesheet never loads here.
   ============================================================ */
.re-chat {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 1030; /* above AdminDek's sticky header (1024), below its modals */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
}

.re-chat-fab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  padding: 0;
  border-radius: 50%;
  background: var(--re-dash-brand);
  color: var(--re-dash-fg-inverse);
  border: 1px solid var(--re-dash-brand-dark);
  box-shadow: 0 6px 18px rgba(15, 23, 42, 0.22);
  cursor: pointer;
  transition: background 0.15s, transform 0.15s, box-shadow 0.15s;
}
.re-chat-fab:hover { background: var(--re-dash-brand-dark); transform: translateY(-1px); }
.re-chat-fab:focus-visible { outline: 2px solid var(--re-dash-brand-dark); outline-offset: 2px; }
.re-chat-fab .ico { display: inline-flex; align-items: center; justify-content: center; }
.re-chat-fab .ico-shut { display: none; }
.re-chat.is-open .re-chat-fab .ico-open { display: none; }
.re-chat.is-open .re-chat-fab .ico-shut { display: inline-flex; }

.re-chat-sheet {
  width: min(300px, calc(100vw - 32px));
  background: var(--re-dash-bg);
  border: 1px solid var(--re-dash-border);
  border-radius: 14px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
  padding: 8px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.18s, transform 0.18s;
}
.re-chat-sheet.is-open { opacity: 1; transform: translateY(0); }

.re-chat-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 8px 8px 12px;
  border-bottom: 1px solid var(--re-dash-border);
  margin-bottom: 8px;
}
.re-chat-sheet-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--re-dash-fg-muted);
}
.re-chat-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border: 0;
  color: var(--re-dash-fg-muted);
  cursor: pointer;
}
.re-chat-close:hover { background: var(--re-dash-bg-header); color: var(--re-dash-fg); }

.re-chat-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--re-dash-fg);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s;
}
/* display:flex above would defeat the UA [hidden] rule — restore it. */
.re-chat-opt[hidden] { display: none; }
.re-chat-opt:hover { background: var(--re-dash-bg-header); color: var(--re-dash-fg); text-decoration: none; }
.re-chat-opt .ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--re-dash-bg-header);
  flex: 0 0 auto;
}
.re-chat-opt .ico-wa    { color: var(--re-dash-success); }
.re-chat-opt .ico-live  { color: var(--re-dash-info); }
.re-chat-opt .ico-jimmy { color: var(--re-dash-warning); }
.re-chat-opt .txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.re-chat-opt .txt b { font-size: 14.5px; font-weight: 600; }
.re-chat-opt .txt small { font-size: 12px; color: var(--re-dash-fg-secondary); }

/* Jimmy is absorbed into this sheet as a row, so its own bubble is retired.
   Class added by my-account.js once Jimmy has mounted. */
.jmy-launcher.re-chat-absorbed { display: none; }

@media (max-width: 600px) {
  .re-chat { right: 16px; bottom: 16px; }
  .re-chat-fab { width: 50px; height: 50px; }
}

/* ── Checkout Leaks (?view=checkout-leaks) ────────────────────────────────────
   Eight columns, and the last one carries six action handles. Left to size
   itself the "What they changed" cell keeps every tag on one line, which pushed
   the table past the viewport and hid the handles behind a horizontal scroll —
   the handles being the reason a counsellor opens this screen at all.
   Capping that one cell lets the tags wrap instead of the table growing.
   Layout only; no colour is declared here, so nothing competes with the
   --re-dash-* set. */
/* The cap lives on an inner block, not the cell: max-width on a <td> is
   ignored under auto table layout, so the tags kept forcing the table wider. */
.odr-checkout-leaks .re-leak-changes__wrap{max-width:280px;white-space:normal;}
/* white-space:nowrap is inherited down onto these cells from the shared
   datatable styling, so the 280px box was the right width but its tags
   still could not break — max-width alone does nothing against nowrap. */
.odr-checkout-leaks .re-leak-changes__wrap .odr-pill{display:inline-block;margin:0 4px 4px 0;}
.odr-checkout-leaks .re-leak-actions{white-space:nowrap;}
.odr-checkout-leaks .re-leak-actions .re-dash-icon-sq{margin-left:2px;}

/* GrowYu rows in the unified activities popup.
   Owner 2026-08-24: keep every GrowYu type — working a project needs the prior
   conversation — which means a project's timeline is mostly the customer's
   conversation (54 of 60 rows on SUB-ID-778221). The eye has to separate "what
   happened to this project" from "what we said to this person" without reading
   every line, so conversation rows sit on a tinted rail rather than a bare row.
   Colour comes from the --re-dash-* set only; nothing new is invented here. */
.odr-activity-table tbody tr.odr-activity-row--growyu > td {
  background: var(--re-dash-info-soft);
}
.odr-activity-table tbody tr.odr-activity-row--growyu > td:first-child {
  box-shadow: inset 4px 0 0 0 var(--re-dash-info);
  /* The accent is drawn INSIDE the cell, so without this the row number sits
     underneath it and reads as clipped. */
  padding-left: 12px;
}
/* The actor on a GrowYu row is a robot, not a customer — it must not read in the
   same green the customer rows use. */
.odr-activity-table tbody tr.odr-activity-row--growyu .odr-activity-who {
  color: var(--re-dash-info-dark) !important; /* beats the .text-success utility the shared row logic puts here */
}
/* Source chip, where a local row shows its role. */
.odr-activity-src--growyu {
  margin-top: 2px;
  padding: 1px 7px;
  border-radius: 10px;
  background: var(--re-dash-info);
  color: var(--re-dash-fg-inverse);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
/* One glyph per kind of activity: with every GrowYu type kept, the labels are a
   wall of similar text and the icon is what the eye scans. */
.odr-activity-icon { color: var(--re-dash-fg-placeholder); width: 14px; text-align: center; }
.odr-activity-row--growyu .odr-activity-icon { color: var(--re-dash-info); }
/* "Customer-wide" where a project id would be. A call belongs to a person, not
   to one of their projects, and saying so beats the blank that used to sit
   there — indistinguishable from a project we simply failed to print. */
.odr-activity-project--none {
  font-size: 11px;
  font-style: italic;
  color: var(--re-dash-fg-placeholder);
}

/* Call-row controls in the activities popup: play the recording, open the last
   analysis. Sit above the label as a small action row, tinted like the GrowYu
   band they live in. */
.odr-activity-play,
.odr-activity-call-analysis {
  display: inline-block;
  margin: 0 6px 4px 0;
  padding: 2px 9px;
  border: 1px solid var(--re-dash-info);
  border-radius: 12px;
  background: var(--re-dash-bg);
  color: var(--re-dash-info-dark);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.odr-activity-play:hover,
.odr-activity-call-analysis:hover {
  background: var(--re-dash-info);
  color: var(--re-dash-fg-inverse);
}
.odr-activity-audio { width: 100%; max-width: 320px; height: 32px; }

/* The AI summary sits on its own line under the recording control, because the
   play button swaps itself for an <audio> element and anything sharing that
   line would end up beside the player.

   It is a card, not a button: GrowYu's summary arrives with the journey, so
   the gist is on the row from the start and only the full analysis is a click
   away. Tinted panel so the machine-written text is never mistaken for a
   counsellor's own note. */
.odr-activity-ai-row { margin: 4px 0 6px; }
.odr-ai-gist {
  border: 1px solid var(--re-dash-border);
  border-left: 3px solid var(--re-dash-brand);
  border-radius: 4px;
  background: var(--re-dash-bg-header);
  padding: 8px 10px;
  max-width: 560px;
}
.odr-ai-gist-title {
  display: block;
  margin-bottom: 6px;
  color: var(--re-dash-brand-dark);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.odr-ai-gist .odr-ai-text { font-size: 12.5px; margin-bottom: 8px; }
.odr-ai-gist .odr-ai-pills { margin-bottom: 8px; }
.odr-activity-ai {
  display: inline-block;
  padding: 2px 9px;
  border: 1px solid var(--re-dash-brand);
  border-radius: 12px;
  background: var(--re-dash-bg);
  color: var(--re-dash-brand-dark);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.odr-activity-ai:hover {
  background: var(--re-dash-brand);
  color: var(--re-dash-fg-inverse);
}

/* ---------------------------------------------------------------------------
   Call AI Summary panel (slide-in). Rendered by functions-call-ai-summary.php.
   --------------------------------------------------------------------------- */
.odr-ai-panel { font-size: 13.5px; color: var(--re-dash-fg); }

.odr-ai-head {
  border-bottom: 1px solid var(--re-dash-border);
  padding-bottom: 10px;
  margin-bottom: 12px;
}
.odr-ai-meta { color: var(--re-dash-fg-muted); font-size: 12px; }

.odr-ai-pills { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.odr-ai-pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 600;
  background: var(--re-dash-bg-header);
  color: var(--re-dash-fg-secondary);
}
.odr-ai-pill--good { background: var(--re-dash-success-soft); color: var(--re-dash-success-dark); }
.odr-ai-pill--bad { background: var(--re-dash-danger-soft); color: var(--re-dash-danger-dark); }

.odr-ai-text { margin: 0 0 10px; line-height: 1.55; }

.odr-ai-note {
  border: 1px solid var(--re-dash-border);
  border-radius: 6px;
  background: var(--re-dash-bg-header);
  padding: 10px 12px;
  margin-bottom: 12px;
}
.odr-ai-note-title {
  display: block;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--re-dash-fg-secondary);
  margin-bottom: 4px;
}
.odr-ai-note .odr-ai-text { margin-bottom: 0; }

.odr-ai-transcript { border-top: 1px solid var(--re-dash-border); padding-top: 10px; }
.odr-ai-transcript > summary {
  cursor: pointer;
  color: var(--re-dash-brand-dark);
  font-weight: 600;
  margin-bottom: 8px;
}

/* Three levels inside the panel, and they must read as three when scrolling:

     panel   — the slide-in itself (.odr-ai-panel)
     section — "Full analysis", "Agent performance" (.odr-ai-section-title):
               the largest type in the panel, sentence case, a rule under it,
               and the most air above it.
     block   — "Call highlights", "Coaching Feedback" (.odr-ai-block-title):
               a small uppercase eyebrow in muted ink, the same voice as the
               "AI summary" title on the row, so it is unmistakably a label
               over content and never a heading of its own.

   Before this the two were 13.5px/700 and 12px/700 in near-identical ink, and
   section boundaries vanished. */

/* Fact strip: the verdict (Interest / Sentiment / Urgency) and the agent
   ratings share one cell so a one-word verdict and a bare score are one
   family. */
.odr-ai-facts { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.odr-ai-fact {
  border: 1px solid var(--re-dash-border);
  border-radius: 6px;
  background: var(--re-dash-bg);
  padding: 6px 12px;
  min-width: 110px;
}
.odr-ai-fact-label {
  display: block;
  font-size: 11px;
  color: var(--re-dash-fg-muted);
}
.odr-ai-fact-value { font-weight: 600; }
/* Ratings carry no maximum in the payload (observed 1, 2, 3 — out of what,
   GrowYu does not say), so the cell shows the number alone, larger and in
   tabular figures, with NO "/5" or bar behind it. A bar would draw a scale we
   do not have. */
.odr-ai-facts--ratings .odr-ai-fact { min-width: 96px; text-align: center; }
.odr-ai-facts--ratings .odr-ai-fact-value {
  display: block;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--re-dash-fg);
  font-variant-numeric: tabular-nums;
}

.odr-ai-block { margin-bottom: 16px; }
.odr-ai-block:last-child { margin-bottom: 0; }
.odr-ai-block-title {
  margin: 0 0 5px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--re-dash-fg-muted);
}
/* The parent stylesheet resets every <ul> to no marker and no indent
   (omak-dash style.css:10 — sidebar and nav lists). This list is prose, so
   the disc comes back; the class outweighs the bare element selector, no
   !important needed. */
.odr-ai-list { margin: 0; padding-left: 20px; list-style: disc outside; }
.odr-ai-list li { display: list-item; margin-bottom: 4px; line-height: 1.5; }
.odr-ai-list li::marker { color: var(--re-dash-fg-muted); }

.odr-ai-section { padding-top: 16px; margin-top: 16px; border-top: 1px solid var(--re-dash-border); }
.odr-ai-section-title {
  margin: 0 0 12px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--re-dash-border-light);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--re-dash-fg);
}

.odr-ai-empty { color: var(--re-dash-fg-muted); line-height: 1.55; }



/* Row layout, reworked 2026-08-25 (owner).
   The meta rail used to stack six lines — number, time, date, who, role,
   project — which made it the tallest thing in every row and set the height of
   the whole card. It is three now: when (one line, number inline), who, role.
   Provenance moved to a fixed corner so it no longer shifts about depending on
   what else the rail is carrying. */
.odr-activity-table tbody td { padding-top: 8px; padding-bottom: 8px; }
.odr-activity-table .odr-activity-sno {
  margin-right: 6px;
  margin-bottom: 0;
}
.odr-activity-table .odr-activity-who { margin-top: 2px; }

/* The corner: project id, or the GrowYu chip and what it means. Reserve room on
   the right of the activity cell so a long message cannot run underneath it. */
.odr-activity-table .odr-activity-what {
  position: relative;
  padding-right: 120px;
}
.odr-activity-corner {
  position: absolute;
  top: 8px;
  right: 0;
  max-width: 112px;
  text-align: right;
  font-size: 11px;
  line-height: 1.5;
}
.odr-activity-corner .odr-activity-src--growyu { margin-top: 0; }

/* ==========================================================================
   TEAM FINDINGS (view-quick-tasks.php)
   A filterable read of quick-task.md. Colour comes only from --re-dash-* tokens;
   the tone names (success/warning/info/danger/muted) map to the status buckets in
   odr_quick_tasks_statuses() so PHP and CSS agree on what a state looks like.
   ========================================================================== */
.re-qt-subtitle { color: var(--re-dash-fg-muted); font-size: 12.5px; }

.re-qt-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.re-qt-chip {
  border: 1px solid var(--re-dash-border);
  background: var(--re-dash-bg);
  color: var(--re-dash-fg-secondary);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.6;
  cursor: pointer;
}
.re-qt-chip:hover { background: var(--re-dash-bg-row-hover); }
.re-qt-chip-count {
  display: inline-block;
  margin-left: 6px;
  color: var(--re-dash-fg-muted);
  font-weight: 500;
}
/* Pressed state: the chip takes its bucket's colour, so which filters are on is
   readable at a glance rather than only from the pressed border. */
.re-qt-chip.is-on { color: var(--re-dash-fg-inverse); }
.re-qt-chip.is-on .re-qt-chip-count { color: var(--re-dash-fg-inverse); }
.re-qt-chip--danger.is-on  { background: var(--re-dash-danger);  border-color: var(--re-dash-danger); }
.re-qt-chip--warning.is-on { background: var(--re-dash-warning); border-color: var(--re-dash-warning); }
.re-qt-chip--info.is-on    { background: var(--re-dash-info);    border-color: var(--re-dash-info); }
.re-qt-chip--success.is-on { background: var(--re-dash-success); border-color: var(--re-dash-success); }
.re-qt-chip--muted.is-on   { background: var(--re-dash-inverse); border-color: var(--re-dash-inverse); }

.re-qt-section {
  margin: 22px 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--re-dash-border);
  color: var(--re-dash-fg-muted);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}

.re-qt-item {
  border: 1px solid var(--re-dash-border);
  border-radius: 6px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--re-dash-bg);
}
.re-qt-item:hover { background: var(--re-dash-bg-row-hover); }

.re-qt-head { display: flex; align-items: baseline; gap: 8px; }
.re-qt-num { color: var(--re-dash-fg-placeholder); font-size: 12px; font-weight: 700; flex: 0 0 auto; }
.re-qt-summary {
  color: var(--re-dash-fg);
  font-size: 13.5px;
  line-height: 1.5;
  /* Some entries open with a paragraph rather than a sentence (item 1 runs to ~1,900
     characters before its first newline), which turned the collapsed row into a wall
     of text. Cap the collapsed view at two lines; the full text is one click away in
     Details, and the search still matches against the whole body. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.re-qt-badge {
  flex: 0 0 auto;
  border-radius: 4px;
  padding: 1px 7px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.re-qt-badge--danger  { background: var(--re-dash-danger-soft);  color: var(--re-dash-danger-dark); }
.re-qt-badge--warning { background: var(--re-dash-warning-soft); color: var(--re-dash-warning-dark); }
.re-qt-badge--info    { background: var(--re-dash-info-soft);    color: var(--re-dash-info-dark); }
.re-qt-badge--success { background: var(--re-dash-success-soft); color: var(--re-dash-success-dark); }
.re-qt-badge--muted   { background: var(--re-dash-border-light); color: var(--re-dash-fg-muted); }

.re-qt-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--re-dash-fg-muted);
}
.re-qt-reporter { font-weight: 600; color: var(--re-dash-fg-secondary); }
.re-qt-area {
  border: 1px solid var(--re-dash-border);
  border-radius: 3px;
  padding: 0 6px;
  color: var(--re-dash-fg-muted);
}
.re-qt-toggle {
  margin-left: auto;
  border: 0;
  background: none;
  padding: 0;
  color: var(--re-dash-info);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}

/* The full item text, shown verbatim. pre-wrap keeps the file's own line breaks and
   indented sub-points readable instead of collapsing them into one paragraph. */
.re-qt-body {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--re-dash-border);
  color: var(--re-dash-fg-secondary);
  font-size: 12.5px;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.re-qt-empty { color: var(--re-dash-fg-muted); font-size: 13px; padding: 18px 0; }

/* Scope dropdown sits inline in the reporting bar, sized to its longest label
   rather than stretching across the row like a form control. */
.odr-vendor-expenses .ve-rpt-scope {
  flex: 0 0 auto;
  width: auto;
  min-width: 220px;
  font-size: .85rem;
}

/* Canonical long-text display (.re-expand*) now lives in omak-dash's stylesheet,
   beside the rel_truncate_string_wrap() helper that emits the markup — a child plugin
   calling the parent's helper must not have to ship the presentation itself. */

/* ============================================================================
   CUSTOMER PROJECT PAGE — stage shell  (.re-pd-*)
   ----------------------------------------------------------------------------
   Presentation for theme/page-templates/my-account/parts/shell/* and
   parts/stages/*. Design: docs/user-view-rework/design/lifecycle/ (artifact "Service Lifecycles")
   Decisions: docs/user-view-rework/DECISIONS.md

   Structure comes from AdminDek and Bootstrap — `card`, `card-block`,
   `row` / `col-lg-*`, `btn` / `btn-mini` / `btn-md` / `btn-outline-*` /
   `btn-success` — the site's own classes, exactly as the design artifact renders
   them (owner, 2026-09-02: follow the artifact WITHOUT reinventing classes that
   already exist). Only the card SURFACE is restated, scoped below: the
   template's cards are a stack of small related panels, and AdminDek's 30px
   margin plus drop shadow reads as six unrelated pages on a phone.

   The mock uses bare class names for its own components (.chip, .steps). Those
   collide with Bootstrap 4 and AdminDek, so COMPONENT INTERNALS with no site
   equivalent are prefixed re-pd-*; anything the site already provides is used
   under its real name. No raw hex: every colour is a --re-dash-* token, and the
   four -line tokens were added to omak-dash's :root for exactly this block (a
   chip on a -soft ground needs an edge that is neither -dark nor neutral grey).
   ============================================================================ */

.re-pd { font-size: 14px; line-height: 1.55; color: var(--re-dash-fg); }

/* ── Where AdminDek's metrics differ from the design's ────────────────────── */
/* Measured, not guessed: tests/qa/ux-audit-project-details compares the computed
   style of each element here against the same element in the design file, and
   these four rules are what that diff reported. */
/* Leading. AdminDek gives headings 1.2 and small text its own tighter values;
   the design runs one rhythm — 1.55 — through everything in the card. */
.re-pd h1, .re-pd h2, .re-pd h3, .re-pd h4, .re-pd h5, .re-pd h6,
.re-pd .card-header h5 { line-height: 1.55; }
/* `.card .card-block p` in the bundle is 0,2,1 and was winning at 1.4, so the
   selector has to reach that far — not !important. */
.re-pd .card .card-block p,
.re-pd .re-pd-tiny, .re-pd .re-pd-gatehint, .re-pd .re-pd-muted { line-height: 1.55; }
/* The file name is set in the display face, like the design's .fname. */
.re-pd-fname { font-family: 'Quicksand', ui-rounded, system-ui, sans-serif; }
/* The design sets its display face (--quick) on every headline figure and card
   title, not only on headings — omak's override maps Quicksand to h1-h6, so
   the div-based numerals and titles here need it named. Same list of roles the
   artifact styles with var(--quick). */
.re-pd-ev-n, .re-pd-sc-v, .re-pd-price, .re-pd-range-v, .re-pd-deliver-t,
.re-pd-offer-title, .re-pd-goodbox-title, .re-pd-statusmsg-t, .re-pd-gbox-t {
    font-family: 'Quicksand', ui-rounded, system-ui, sans-serif;
}
/* AdminDek's buttons are 2px-radius and weight 400. The design's are 8px and
   500 — the difference between a control that looks stamped on and one that
   belongs to the card it sits in. */
.re-pd .btn { border-radius: 8px; font-weight: 500; }
/* AdminDek's info is Bootstrap teal (#17a2b8); the design's is the panel's own
   --re-dash-info-dark. Only inside .re-pd, so every other screen keeps teal. */
.re-pd .btn-outline-info {
    color: var(--re-dash-info-dark);
    border-color: var(--re-dash-info-dark);
    background: var(--re-dash-bg);
}
.re-pd .btn-outline-info:hover, .re-pd .btn-outline-info:focus {
    color: var(--re-dash-fg-inverse);
    background: var(--re-dash-info-dark);
    border-color: var(--re-dash-info-dark);
}

/* Applies to the stage's own cards AND to the cards other helpers return whole —
   REL_KNOWLEDGEBASE::get_faq_card() and generate_referral_card() both emit a
   complete .card, so they are echoed directly rather than wrapped in one.
   Direct children of the stage and of its grid columns ONLY: helpers with their
   own card chrome nested deeper (get_checkout_html()'s .re-ck cards) keep it. */
.re-pd > .card,
.re-pd .row > [class*="col-"] > .card {
    border: 1px solid var(--re-dash-border);
    border-radius: var(--re-dash-control-radius);
    box-shadow: none;
    margin-bottom: 12px;
}
/* The shared checkout sits between stage cards with no margin of its own, so the
   card under it touched it (0px where every other gap is 12px). */
.re-pd > #checkout-html { margin-bottom: 12px; }
/* The artifact's .sep hairline, as the element the site already has. */
.re-pd hr { border: 0; border-top: 1px solid var(--re-dash-border-light); margin: 14px 0; }
.re-pd .card > .card-block,
.re-pd .card > .card-body { padding: 16px; }
.re-pd .card > .card-header { padding: 14px 16px 0; border-bottom: 0; background: none; }
.re-pd .card > .card-header h5 { margin: 0; font-size: 16px; font-weight: 700; }
/* AdminDek draws a decorative 60px grey bar 20px BELOW every card heading
   (`.card .card-header h5:after`, style.css:228). It is built for its own 20px
   header padding, where the block starts far enough down to clear it; in these
   cards the content follows immediately, so the bar landed inside the first row
   — the stray line the owner saw under "What you get" and "Before you pay" —
   and made the heading look glued to the content. Removed here only; every
   other screen keeps it. */
.re-pd .card > .card-header h5:after { content: none; }
/* The design's own separation: air under the heading, then the body. */
.re-pd .card > .card-header + .card-block,
.re-pd .card > .card-header + .card-block > .accordion-block { padding-top: 14px; }
.re-pd h5 { font-size: 16px; font-weight: 700; margin: 0 0 4px; }
.re-pd p { margin: 0 0 10px; }
.re-pd p:last-child { margin-bottom: 0; }
.re-pd-muted { color: var(--re-dash-fg-secondary); font-size: 13px; }
.re-pd-tiny  { color: var(--re-dash-fg-muted); font-size: 12px; }

/* Two columns from 992px up — Bootstrap's own grid (`row` + col-lg-8/col-lg-4),
   the same split the artifact's desktop view draws. Below lg it is one stack, in
   DOM order — which is why the stage templates put the decision (pay, download)
   before the reassurance. No private grid classes here on purpose. */

/* ── Identity bar ────────────────────────────────────────────────────────── */
.re-pd-idbar { display: flex; flex-direction: column; gap: 12px; }
.re-pd-idrow { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.re-pd-idmain { min-width: 0; }
.re-pd-pid { font-size: 13px; color: var(--re-dash-fg-secondary); }
/* The old header let a 90-character filename push the status chip off a 360px
   screen. The two-line clamp now sits on .copy-text (see the D32 block below),
   because the name gained a hover copy icon that must NOT be clipped with it. */
.re-pd-fname {
    font-weight: 700; font-size: 16px; line-height: 1.3; margin-top: 3px; word-break: break-word;
}
.re-pd-fmeta { font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 3px; }

/* ── Status chip ─────────────────────────────────────────────────────────── */
/* 13px dark-on-soft, 28px tall. The `label bg-*` chips it replaces were 9px white
   on solid and measured 1.63:1 at worst — see tests/qa/ux-audit-project-details. */
.re-pd-chip {
    display: inline-flex; align-items: center; white-space: nowrap;
    font-size: 13px; font-weight: 600; line-height: 1;
    padding: 7px 11px; min-height: 28px; border-radius: 999px; border: 1px solid;
}
.re-pd-chip--new   { color: var(--re-dash-info-dark);      background: var(--re-dash-info-soft);    border-color: var(--re-dash-info-line); }
.re-pd-chip--ready { color: var(--re-dash-warning-dark);   background: var(--re-dash-warning-soft); border-color: var(--re-dash-warning-line); }
.re-pd-chip--done  { color: var(--re-dash-success-darker); background: var(--re-dash-success-soft); border-color: var(--re-dash-success-line); }
.re-pd-chip--hold  { color: var(--re-dash-warning-dark);   background: var(--re-dash-warning-soft); border-color: var(--re-dash-warning-line); }
.re-pd-chip--ref,
.re-pd-chip--err   { color: var(--re-dash-danger-dark);    background: var(--re-dash-danger-soft);  border-color: var(--re-dash-danger-line); }

/* ── Lifecycle strip ─────────────────────────────────────────────────────── */
/* `at` (amber) is the customer's move, `now` (blue) is ours. They must not look
   alike: on the pay gate that difference is the entire message. */
.re-pd-steps { display: flex; gap: 6px; }
.re-pd-step { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.re-pd-step-bar { height: 4px; border-radius: 2px; background: var(--re-dash-border); }
.re-pd-step-lb {
    font-size: 12px; font-weight: 600; color: var(--re-dash-fg-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Five and six-step strips (the removal family) do not fit on one line at 390px:
   "Submitt… Quote C… Pay Adv… In Progr…" is four truncated words where the whole
   point is that the customer can read where they are. Longer strips wrap to two
   lines instead of truncating. */
.re-pd-steps--long .re-pd-step-lb {
    white-space: normal; font-size: 11px; line-height: 1.25;
    overflow-wrap: normal; word-break: keep-all; hyphens: none; /* wrap between words, never "Submitte/d" */
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
@media (min-width: 768px) {
    .re-pd-steps--long .re-pd-step-lb { font-size: 12px; }
}
.re-pd-step--ok  .re-pd-step-bar { background: var(--re-dash-success-darker); }
.re-pd-step--ok  .re-pd-step-lb  { color: var(--re-dash-fg-secondary); }
.re-pd-step--at  .re-pd-step-bar { background: var(--re-dash-warning-dark); }
.re-pd-step--at  .re-pd-step-lb  { color: var(--re-dash-warning-dark); }
.re-pd-step--now .re-pd-step-bar { background: var(--re-dash-info-dark); }
.re-pd-step--now .re-pd-step-lb  { color: var(--re-dash-info-dark); }

/* ── Files ───────────────────────────────────────────────────────────────── */
.re-pd-filerow {
    display: flex; align-items: center; gap: 10px; padding: 10px 12px;
    border: 1px solid var(--re-dash-border); border-radius: var(--re-dash-control-radius);
    background: var(--re-dash-bg-header);
}
.re-pd-filerow-ico { color: var(--re-dash-fg-muted); font-size: 16px; }
.re-pd-filerow-fx { flex: 1; min-width: 0; }
.re-pd-filerow-fl { display: block; font-size: 12.5px; color: var(--re-dash-fg-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 44px, the tap-target floor. The old download links were 20px text. */
.re-pd-dlico {
    flex: 0 0 44px; width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--re-dash-border); border-radius: var(--re-dash-control-radius);
    background: var(--re-dash-bg); color: var(--re-dash-fg-secondary); text-decoration: none;
}
.re-pd-dlico:hover, .re-pd-dlico:focus { color: var(--re-dash-brand-dark); border-color: var(--re-dash-brand-dark); text-decoration: none; }

/* Centred, at content width. A column flex container stretches its children,
   which made every download button full-width — right for the deliverable,
   wrong for a secondary download sitting under it. */
.re-pd-dlgrid { display: flex; flex-direction: column; align-items: center; gap: 8px; }
/* D48 — both reports paid: the two downloads share ONE row at every width,
   equal widths, nowrap (the artifact's .dlpair). Stacked on a phone the card
   read as two separate offers (owner, 2026-09-02). */
.re-pd-dlgrid--pair { flex-direction: row; flex-wrap: nowrap; align-items: stretch; }
.re-pd-dlgrid--pair .btn { flex: 1 1 0; min-width: 0; white-space: nowrap; }
/* The deliverable download — the one thing they came for. D49: dark, ordinary
   height, labelled by the FILE — `btn btn-dark` in the template (file-row.php),
   with a second paid file as `btn btn-outline-dark` beside it. Green is for
   money alone now; the colour rules live in the button block below. */
.re-pd-dlsz { margin-left: auto; font-weight: 500; font-size: 12px; opacity: .85; }

/* Files deleted is not housekeeping — it is the one irreversible thing on this
   screen, and the customer needs to read it as such (owner, 2026-09-03). Danger
   tokens, but SOFT: a dashed red hairline on a tinted ground, not a filled
   alert. It reports a state the customer chose, it does not warn them off. */
.re-pd-removed {
    display: flex; align-items: center; gap: 9px; padding: 11px 13px;
    border: 1px dashed var(--re-dash-danger-line); border-radius: var(--re-dash-control-radius);
    background: var(--re-dash-danger-soft); font-size: 12.5px; color: var(--re-dash-danger-dark);
}
.re-pd-removed i, .re-pd-removed .fa, .re-pd-removed .fad { color: var(--re-dash-danger-dark); }

/* ── Evidence tiles (words / pages / sources) ────────────────────────────── */
/* Safe facts only. Nothing in this block may be derived from the similarity
   score before payment — see D3. */
.re-pd-ev {
    display: grid; gap: 1px; margin: 14px 0; overflow: hidden;
    background: var(--re-dash-border); border: 1px solid var(--re-dash-border);
    border-radius: var(--re-dash-control-radius);
}
.re-pd-ev--one   { grid-template-columns: 1fr; } /* one fact (files-removed screen, no style on file) */
.re-pd-ev--two   { grid-template-columns: repeat(2, 1fr); }
.re-pd-ev--three { grid-template-columns: repeat(3, 1fr); }
/* Four tiles go 2x2, not 3+1. A lone tile on a second row reads as an error. */
.re-pd-ev--four  { grid-template-columns: repeat(2, 1fr); }
/* min-width:0 and the wrap: a grid cell will not shrink below its longest word,
   so a single long value ("Management") pushed the whole tile row 8px past its
   container in the narrow desktop column — clipped, with no scrollbar. */
.re-pd-ev > div { background: var(--re-dash-bg); padding: 12px 10px; text-align: center; min-width: 0; overflow-wrap: anywhere; }
/* The value and its label carry the tile surface and padding themselves — the
   design's `.ev div` rule reaches the nested divs too, and the approved mock
   renders (and the parity harness measures) that air inside every tile. */
.re-pd-ev-n { font-weight: 700; font-size: 20px; background: var(--re-dash-bg); padding: 12px 10px; }
.re-pd-ev-n--sm { font-size: 15px; }
.re-pd-ev-k { font-size: 11px; color: var(--re-dash-fg-muted); margin-top: 2px; line-height: 1.3; background: var(--re-dash-bg); padding: 12px 10px; }
.re-pd-declared { font-size: 11.5px; color: var(--re-dash-fg-muted); text-align: center; margin-top: -4px; }
/* Why this many pages, on a quote screen: the first thing under the status strip, so it reads as text, not a footnote. */
.re-pd .re-pd-pages-why { font-size: 15px; line-height: 1.5; color: var(--re-dash-fg); margin: 0; }
/* The count is above what the customer chose: the "Page range updated." lead reads as a notice (removal quote, 2026-10-15). */
.re-pd .re-pd-page-correction strong { color: var(--re-dash-warning-dark); }
/* What the service does and does not do, under the price or the in-progress line (Citation Formatting C4, Proofreading PR4, 2026-10-14). */
.re-pd .re-pd-scope { font-size: 14px; line-height: 1.5; color: var(--re-dash-fg-secondary); margin: 8px 0 0; }
.re-pd .re-pd-pages-why + .re-pd-scope { margin-top: 6px; }
/* The 7-day changes line under the delivered downloads (P7, 2026-10-14). */
.re-pd .re-pd-changes { font-size: 14px; color: var(--re-dash-fg-secondary); text-align: center; margin: 12px 0 0; }
/* The checkout's "Pay ₹X (50%) to start" line above the pay button (P4, 2026-10-14). */
/* ==========================================================================
   THE CHECKOUT — ODR_PROJECTS::get_checkout_html() (artifact "Service Lifecycles",
   DF page #pay-before; owner 14 Oct 2026: every line kept, no boxes inside boxes).
   Two flat cards (what is bought / the order), thin dividers. The same block on the
   project page and on /pay. The pay widget inside comes from omak-dash
   REL_MONEYRAM::create_pay_now_buttons(), which other screens also use — so its boxes
   are flattened HERE, scoped to .re-ck, never in its own markup.
   ========================================================================== */
.re-ck { color: var(--re-dash-fg); }
.re-ck .re-ck-card { border: 1px solid var(--re-dash-border); box-shadow: none; border-radius: var(--re-dash-control-radius); margin-bottom: 16px; }
.re-ck .re-ck-card > .card-block { padding: 18px; }
.re-ck-title { font-size: 16px; font-weight: 700; margin: 0; color: var(--re-dash-fg); }
.re-ck-sub { font-size: 13px; color: var(--re-dash-fg-secondary); margin: 2px 0 12px; }
.re-ck-line { font-size: 13.5px; line-height: 1.5; margin: 0 0 10px; color: var(--re-dash-fg-secondary); }
.re-ck-line strong { color: var(--re-dash-fg); }
.re-ck-small { font-size: 12.5px; line-height: 1.5; color: var(--re-dash-fg-secondary); margin: 4px 0 10px; }
.re-ck-warn { color: var(--re-dash-danger-dark); }
.re-ck-sep { border-top: 1px solid var(--re-dash-border-light); margin: 12px 0; }
.re-ck-trust { margin-bottom: 0; }

.re-ck-svc { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--re-dash-border-light); }
.re-ck-svc:last-of-type { border-bottom: 0; }
.re-ck-svc-main { flex: 1; min-width: 0; }
.re-ck-svc-name { font-size: 14.5px; font-weight: 600; color: var(--re-dash-fg); }
.re-ck-svc-meta { font-size: 12.5px; color: var(--re-dash-fg-secondary); }
.re-ck-svc-price { font-size: 13.5px; font-weight: 600; margin-top: 2px; }
.re-ck-was { color: var(--re-dash-danger-dark); font-weight: 600; margin-right: 4px; }
.re-ck-now { color: var(--re-dash-success-darker); }
.re-ck-off { font-size: 12px; font-weight: 400; color: var(--re-dash-fg-muted); margin-left: 4px; }
.re-ck-badge { display: inline-block; font-size: 11px; font-weight: 600; padding: 1px 8px; border-radius: 999px; margin-left: 6px; vertical-align: middle; background: var(--re-dash-bg-header); color: var(--re-dash-fg-secondary); }
.re-ck-badge--pri { background: var(--re-dash-info-soft); color: var(--re-dash-info-dark); }
.re-pd #checkout-html-reports #rzp-button { width: 100%; min-height: 48px; } /* the balance Pay: full width, as on the quote */
.re-pd-paysum-t { font-size: 16px; font-weight: 700; margin: 0 0 10px; }
.re-pd-ledger.re-pd-ledger--flat { border: 0; border-radius: 0; } /* two classes: the base .re-pd-ledger rule comes later in this file */
.re-pd-ledger.re-pd-ledger--flat > div { padding: 9px 0; }
.re-pd-payrest { text-align: center; }
.re-ck-inc { font-size: 13px; font-weight: 600; color: var(--re-dash-success-darker); white-space: nowrap; }
.re-ck-svc-act { flex-shrink: 0; }

.re-ck-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 6px 0; }
.re-ck-row-k { font-size: 13.5px; font-weight: 600; color: var(--re-dash-fg); }
.re-ck-ctl { display: flex; align-items: center; gap: 8px; }
.re-ck-ctl select.form-control { width: auto; min-width: 190px; height: var(--re-dash-control-h); padding: 4px 10px; font-size: 13.5px; border: 1px solid var(--re-dash-border); border-radius: var(--re-dash-control-radius); background-color: var(--re-dash-bg); }

.re-ck-fee { display: flex; justify-content: space-between; gap: 12px; font-size: 13.5px; padding: 4px 0; }
.re-ck-fee > span:last-child { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.re-ck-minus { color: var(--re-dash-danger-dark); }
.re-ck-final { font-weight: 600; }
.re-ck-breakup { margin: 6px 0; }
.re-ck-saving { font-size: 13px; font-weight: 600; color: var(--re-dash-success-darker); margin: 6px 0; }

.re-ck-pricehead { display: grid; grid-template-columns: auto 1fr; column-gap: 14px; align-items: start; margin-top: 12px; }
.re-ck-pricek { font-size: 13px; color: var(--re-dash-fg-secondary); }
.re-ck-plan { font-size: 13px; color: var(--re-dash-fg-secondary); line-height: 1.45; }
.re-ck-price { grid-column: 1 / -1; font-size: 30px; font-weight: 700; line-height: 1.15; color: var(--re-dash-fg); }

/* The pay widget, flattened (its own boxes are for the other screens that use it). */
.re-ck-pay { text-align: left; }
/* The checkout calls create_pay_now_buttons() with `flat`, so the widget writes no
   border, p-3, my-N, text-center or f-18 utilities and nothing here needs !important. */
.re-ck-pay .rel-pay-pif { padding: 0; margin: 0 0 12px; }
.re-ck-pay #yes-get-id { font-size: 13.5px; font-weight: 600; }
.re-ck-pay .rel-pay-pif-note { font-size: 13px; color: var(--re-dash-fg-secondary); }
.re-ck-pay #yes-get-id input { margin: 0 6px 0 0; vertical-align: -1px; }
.re-ck-pay #yes-get-id label { margin: 0; cursor: pointer; }
.re-ck-pay .rel-pay-button-credits.bg-color-box { display: flex; flex-direction: column; align-items: stretch; gap: 10px; background: none; box-shadow: none; padding: 0; margin: 0; font-weight: 400; cursor: default; }
.re-ck-pay .odr-credits-box { border: 0; box-shadow: none; padding: 0; background: none; font-size: 13.5px; }
.re-ck-pay .rel-pay-pif-note p { font-size: 13px; line-height: 1.5; }
.re-ck-pay .odr-convert-report { border-top: 1px solid var(--re-dash-border-light); margin-top: 14px; padding-top: 12px; font-size: 13px; color: var(--re-dash-fg-secondary); }
.re-ck-pay .odr-convert-report strong { color: var(--re-dash-fg); }
.re-ck-pay #rzp-button { width: 100%; min-height: 48px; }
.re-ck-pay .rzp-secure-note { text-align: center; }

@media (max-width: 576px) {
    .re-ck .re-ck-card > .card-block { padding: 14px; }
    .re-ck-row.re-ck-date { flex-direction: column; align-items: stretch; }
    .re-ck-ctl select.form-control { width: 100%; }
    .re-ck-price { font-size: 26px; }
}

.re-pd-locked {
    display: flex; align-items: center; gap: 10px; padding: 12px 14px;
    border: 1px dashed var(--re-dash-border); border-radius: var(--re-dash-control-radius);
    background: var(--re-dash-bg-header); font-size: 13px; color: var(--re-dash-fg-secondary);
}

.re-pd-unlock { list-style: none; margin: 0; padding: 0; }
.re-pd-unlock li { display: flex; gap: 9px; font-size: 13.5px; margin-bottom: 9px; color: var(--re-dash-fg-secondary); }
.re-pd-unlock li:last-child { margin-bottom: 0; }
.re-pd-unlock b { color: var(--re-dash-fg); font-weight: 600; }
.re-pd-tick { color: var(--re-dash-success-darker); font-weight: 700; flex: 0 0 auto; }

/* ── Guidelines box (Document Formatting, 2026-10-03) ────────────────────── */
/* The one component that page adds. Three states: invite (optional, neutral),
   ask (the stage's one request), have (one quiet "Formatted to" line). */
.re-pd-gbox {
    border: 1px dashed var(--re-dash-fg-muted); border-radius: var(--re-dash-control-radius);
    padding: 14px; background: var(--re-dash-bg-header);
}
.re-pd-gbox--ask {
    border: 1px solid var(--re-dash-warning-line); border-left: 3px solid var(--re-dash-warning-dark);
    background: var(--re-dash-warning-soft);
}
.re-pd-gbox--have { position: relative; border: 1px solid var(--re-dash-success-line); background: var(--re-dash-bg); } /* relative: the Change summary is lifted into the row (have state, below) */
.re-pd-gbox-t { font-weight: 700; font-size: 15px; color: var(--re-dash-fg); margin-bottom: 4px; }
.re-pd-gbox-styles { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 12px; padding: 0; border: 0; }
.re-pd-gbox-sty { position: relative; margin: 0; cursor: pointer; }
.re-pd-gbox-sty input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.re-pd-gbox-sty span {
    display: inline-block; font-size: 12.5px; padding: 6px 11px; border-radius: 999px;
    border: 1px solid var(--re-dash-border); background: var(--re-dash-bg); color: var(--re-dash-fg-secondary);
}
.re-pd-gbox-sty input:checked + span { border-color: var(--re-dash-fg); color: var(--re-dash-fg); font-weight: 600; }
.re-pd-gbox-sty input:focus-visible + span { outline: 2px solid var(--re-dash-info); outline-offset: 1px; }
.re-pd-gbox-note { min-height: 62px; resize: vertical; }
/* Last visible line in the box: without this its 10px margin added to the box's
   padding and the bottom sat 10px deeper than the top. */
.re-pd-gbox .re-pd-gatehint { margin-bottom: 0; }
.re-pd-gbox-change { margin-top: 10px; }
.re-pd-gbox-change > summary { list-style: none; }
.re-pd-gbox-change > summary::-webkit-details-marker { display: none; }

/* ── Price + pay ─────────────────────────────────────────────────────────── */
.re-pd-pricehead { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.re-pd-pricek { font-size: 12px; color: var(--re-dash-fg-muted); }
.re-pd-price { font-weight: 700; font-size: 29px; line-height: 1.1; }
/* create_pay_now_buttons() emits this itself — style it, never print a second one. */
.re-pd .rzp-secure-note { color: var(--re-dash-fg-muted); font-size: 12px; margin-top: 10px; text-align: center; }

/* ── Score display (delivered only) ──────────────────────────────────────── */
.re-pd-scores {
    display: grid; grid-template-columns: 1fr 1fr; gap: 1px; overflow: hidden;
    background: var(--re-dash-border); border: 1px solid var(--re-dash-border);
    border-radius: var(--re-dash-control-radius);
}
.re-pd-scores--single { grid-template-columns: 1fr; }
.re-pd-sc { background: var(--re-dash-bg); padding: 16px 14px; text-align: center; }
/* D25: the second slot is laid out and deliberately dimmed while
   ODR_MISC::SHOW_QUOTED_VALUES is true. Business decision, not a bug. */
.re-pd-sc--muted { opacity: .45; }
.re-pd-sc-v { font-weight: 700; font-size: 34px; line-height: 1.1; }
.re-pd-sc-v--hi { color: var(--re-dash-danger-dark); }
.re-pd-sc-v--lo { color: var(--re-dash-success-darker); }
/* AI tiers between the two: low reads plain, moderate amber (odr_ai_value_reading tone). */
.re-pd-sc-v--neutral { color: var(--re-dash-fg); }
.re-pd-sc-v--mid { color: var(--re-dash-warning-dark); }
.re-pd-sc-k { font-size: 11.5px; color: var(--re-dash-fg-muted); margin-top: 4px; line-height: 1.35; }

/* Bands are the service page's: under 10 accepted, 10-25 review, 25+ rejected. */
.re-pd-scale {
    height: 8px; border-radius: 4px; margin-top: 14px; position: relative;
    background: linear-gradient(90deg,
        var(--re-dash-success-darker) 0%, var(--re-dash-success-darker) 25%,
        var(--re-dash-warning) 25%, var(--re-dash-warning) 50%,
        var(--re-dash-danger-dark) 50%, var(--re-dash-danger-dark) 100%);
}
.re-pd-scale-pin { position: absolute; top: -5px; width: 3px; height: 18px; background: var(--re-dash-fg); border-radius: 2px; }
.re-pd-scalelabels { display: flex; justify-content: space-between; font-size: 11px; color: var(--re-dash-fg-muted); margin-top: 6px; }

/* ── Offers ──────────────────────────────────────────────────────────────── */
.re-pd-offer { border: 1px solid var(--re-dash-border); border-radius: var(--re-dash-control-radius); overflow: hidden; }
.re-pd-offer--lead { border-color: var(--re-dash-danger-dark); }
.re-pd-offer-head { padding: 13px 15px; background: var(--re-dash-danger-soft); border-bottom: 1px solid var(--re-dash-danger-line); }
.re-pd-offer-title { font-weight: 700; font-size: 15px; color: var(--re-dash-danger-dark); }
.re-pd-offer-sub { font-size: 12.5px; color: var(--re-dash-fg-secondary); margin-top: 2px; }
.re-pd-offer-body { padding: 14px 15px; }
.re-pd-offer-price { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 10px 0 12px; }
.re-pd-offer-amt { font-weight: 700; font-size: 20px; }
.re-pd-qline { font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 8px; }
/* D50 — two problems, two offers, side by side. The both-over document gives
   the customer three choices — fix one, fix the other, fix both — and a single
   card with a link underneath hid the third. Stacks below 760px, the more
   urgent single problem first (DOM order). */
/* stretch, not start: two offers of different text lengths ended at different
   heights, which reads as one being an afterthought. The bodies grow instead. */
.re-pd-offerpair {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px; align-items: stretch;
}
.re-pd-offerpair > .re-pd-offer { display: flex; flex-direction: column; }
.re-pd-offerpair > .re-pd-offer > .re-pd-offer-body { flex: 1 1 auto; }
@media (max-width: 760px) {
    .re-pd-offerpair { grid-template-columns: 1fr; }
}
/* The "Reduce both" card is an OPTION, not an alarm: neutral head, plain
   border — the red edging belongs to the urgent single problem beside it. */
.re-pd-offer--both { border-color: var(--re-dash-border); }
.re-pd-offer--both .re-pd-offer-head {
    background: var(--re-dash-bg-header);
    border-bottom-color: var(--re-dash-border);
}
.re-pd-offer--both .re-pd-offer-title { color: var(--re-dash-fg); }

/* ── The deliverable card ────────────────────────────────────────────────── */
/* The thing they paid for, given its own weight. It used to be a hairline
   button in a plain card, indistinguishable from the help card beside it. The
   tinted head names what the file IS; the download inside is the one filled
   control on the screen. */
.re-pd-deliver { border-color: var(--re-dash-success-line); }
.re-pd-deliver .re-pd-deliver-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 13px 16px; background: var(--re-dash-success-soft);
    border-bottom: 1px solid var(--re-dash-success-line);
}
.re-pd-deliver-k {
    font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
    color: var(--re-dash-success-darker);
}
.re-pd-deliver-t { font-weight: 700; font-size: 16px; color: var(--re-dash-fg); margin-top: 2px; }
/* The head's right-hand meta — "PDF · 8 pages" (artifact .dmeta). Extension +
   page count only: both are already resolved when the head renders, and a byte
   size would cost a storage call per view — which is why file-row.php already
   refuses to print one. Nothing existing fits: .re-pd-tiny is the wrong colour
   for the tinted head and .re-pd-deliver-k is an uppercase kicker. */
.re-pd-deliver-m { font-size: 11.5px; color: var(--re-dash-success-darker); white-space: nowrap; }

/* The add-on as a ROW inside the deliverable card (artifact `.addon`). The row
   itself is Bootstrap's own `media align-items-center` + `media-body`; only the
   two text treatments are ours, because Bootstrap's `.small`/`.text-muted` carry
   hardcoded greys and the design system requires token colours. */
.re-pd-addon-t { font-weight: 600; font-size: 13.5px; }
.re-pd-addon-s { font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 2px; }

/* ── The quotation, as a range (D37) ─────────────────────────────────────── */
/* The screen used to print the 24-hour price and "delivery within 24 hours",
   while the five-day price — the same work, 40% less — existed only inside a
   modal nobody opened. Both ends show, and the reason the price moves. */
.re-pd-range {
    border: 1px solid var(--re-dash-border); border-radius: var(--re-dash-control-radius);
    overflow: hidden; margin: 12px 0;
}
.re-pd-range-head { padding: 12px 14px; background: var(--re-dash-bg-header); }
.re-pd-range-v { font-weight: 700; font-size: 19px; font-variant-numeric: tabular-nums; }
.re-pd-range-k { font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 2px; }
/* The low→high strip between the two ends. The artifact renders this exact
   gradient (soft success into soft warning) — one of the two gradients the
   design itself draws, so it is allowed here and nowhere near a button. */
.re-pd-range-bar {
    height: 6px; border-radius: 3px; margin: 12px 14px 0;
    background: linear-gradient(90deg, var(--re-dash-success-soft), var(--re-dash-warning-soft));
}
.re-pd-range-ends {
    display: flex; justify-content: space-between; gap: 10px; padding: 6px 14px 11px;
    font-size: 12px;
    color: var(--re-dash-fg-secondary);
}
.re-pd-range-ends b { font-variant-numeric: tabular-nums; }

/* The file name in the header is the download (D32), and long names are the
   norm — "SUB-ID-779048_final-project-file.docx". Two lines, then ellipsis; the
   hover copy icon sits outside the clamp so it stays reachable. */
.re-pd-fname .copy-text {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; vertical-align: bottom;
}
.re-pd-fname .copy-text a { color: inherit; border-bottom: 1px solid var(--re-dash-border); }
.re-pd-fname .copy-text a:hover, .re-pd-fname .copy-text a:focus {
    color: inherit; text-decoration: none; border-bottom-color: var(--re-dash-fg-secondary);
}

/* ── Buttons: the site's own classes, never a second set (D35 / D39 / D49) ── */
/* Full size is reserved for money and the deliverable — Pay (green) and the
   download, which D49 made DARK at ordinary height: green marks money alone
   now, and every file the customer owns is `btn-dark`, a second one beside it
   `btn-outline-dark` in the same row. Everything else is `btn btn-mini` plus
   an outline, the same pair the editor detail view uses. Filled mini actions
   stay `btn-success` — the flat brand green this file already paints (:488) —
   NOT btn-grd-success: AdminDek paints that as a turquoise gradient, which the
   artifact never draws on a button (owner, 2026-09-02). */
/* AdminDek's global `.btn` (omak style.css:8484) sets text-transform:
   capitalize, which re-cased every sentence-case label into Title Case —
   "Download Your Plagiarism Report", "Delete My Files". The template strings
   are already sentence case; only the transform is wrong, and only here. The
   shared rule is untouched because the legacy screens wrote their labels
   expecting it. */
.re-pd .btn { text-transform: none; }
/* AdminDek's own late .btn-success (omak style.css:8809) is a flat TURQUOISE
   (#2ed8b6) that outloads the bare override at the top of this file, exactly as
   it does for the referral card — which already wins it back with a scoped
   `.odr-refer-actions .btn-success`. Same move here: inside the stage view the
   filled action is the brand green the artifact renders and the pay button
   (#rzp-button above) already uses. Tokens, not a second palette. */
.re-pd .btn-success {
    background: var(--re-dash-brand-dark);
    border-color: var(--re-dash-brand-dark);
    color: var(--re-dash-fg-inverse);
}
.re-pd .btn-success:hover,
.re-pd .btn-success:focus,
.re-pd .btn-success:active {
    background: var(--re-dash-success-darker);
    border-color: var(--re-dash-success-darker);
    color: var(--re-dash-fg-inverse);
}
/* D49 — every download is DARK, and dark here is the design's ink pair
   (--re-dash-fg on --re-dash-bg), not AdminDek's slate --re-dash-inverse: the
   artifact's .btn-dark is the fg token, and the two must measure identical in
   the parity harness. Scoped to .re-pd so every other screen keeps the slate. */
.re-pd .btn-dark {
    background: var(--re-dash-fg);
    border-color: var(--re-dash-fg);
    color: var(--re-dash-bg);
    font-weight: 600;
}
.re-pd .btn-dark:hover,
.re-pd .btn-dark:focus,
.re-pd .btn-dark:active {
    background: var(--re-dash-fg-secondary);
    border-color: var(--re-dash-fg-secondary);
    color: var(--re-dash-bg);
}
/* D46 — btn-outline-dark replaces btn-outline-secondary on these screens: the
   grey hairline was too faint to read as a control against a white card. The
   border is fg-secondary, the label full ink — the artifact's own values. The
   explicit hover keeps the fill-on-hover AdminDek's rule would otherwise lose
   to this later, equally-specific one. */
.re-pd .btn-outline-dark {
    color: var(--re-dash-fg);
    border-color: var(--re-dash-fg-secondary);
    background: var(--re-dash-bg);
}
.re-pd .btn-outline-dark:hover,
.re-pd .btn-outline-dark:focus {
    color: var(--re-dash-bg);
    background: var(--re-dash-fg);
    border-color: var(--re-dash-fg);
}
/* The two downloads are the only full-size buttons in the stage view, and they
   live in the deliverable card. AdminDek's .btn base is 15px/10-19 — the
   design's is 12.5px/10-14 at a 44px floor, and the parity harness measures
   the difference. :not(.btn-mini) leaves the card's mini controls (delete,
   add-on) to the mini metrics they already have. */
.re-pd .re-pd-deliver .btn:not(.btn-mini) {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    font-size: 12.5px; line-height: 1.1; padding: 10px 14px; min-height: 44px;
}
.re-pd-btnrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* A row holding one button centres it, and leaves room before the sentence
   that explains it (owner, 2026-09-02). */
.re-pd-btnrow--one { justify-content: center; }
/* D45 — a centred row of SEVERAL: "View charges & dates" sits centred WITH its
   pair, and the compact referral actions centre the same way. Not --one,
   because --one's sibling rules also centre the caption under a single
   control, which these rows do not want. */
.re-pd-btnrow--center { justify-content: center; }
.re-pd-btnrow--one + .re-pd-gatehint,
.re-pd-btnrow--one + .re-pd-tiny,
.re-pd-dlgrid + .re-pd-gatehint { text-align: center; }
.re-pd-btnrow + .re-pd-gatehint,
.re-pd-btnrow + .re-pd-tiny,
.re-pd-btnrow + .re-pd-qline,
.re-pd-btnrow + .re-pd-muted { margin-top: 12px; }
/* Inside the deliverable card a caption belongs TO its centred control: the
   artifact groups "Delete my files" and its explanation as one tight centred
   unit at the card's foot. Full-width prose under a small centred button read
   as two unrelated things at desktop widths. Capped at roughly the artifact's
   measure and centred, the pair reads as one. Deliverable card only — the
   other stages' captions were built and reviewed full-width. */
.re-pd-deliver .re-pd-btnrow--one + .re-pd-gatehint,
.re-pd-deliver .re-pd-dlgrid + .re-pd-gatehint { max-width: 56ch; margin-left: auto; margin-right: auto; }
/* btn-mini is 10px type with 5/10 padding — about 24px tall, well under the
   tap-target floor this audit measured 20 failures against. It keeps its size
   and gains the target through a pseudo-element, which is the trick D11 already
   approved for the credits info button: the touch area grows, the layout does
   not move. Scoped to .re-pd so the admin datatables that use btn-mini in dense
   rows are untouched. */
.re-pd .btn-mini { position: relative; }
.re-pd .btn-mini::after { content: ''; position: absolute; inset: -11px -6px; }
/* A disabled control still reads as a control (D16): shown with the reason,
   never hidden. Bootstrap only styles [disabled] on real buttons. */
.re-pd .btn.disabled, .re-pd .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; pointer-events: none; }

/* The 39% case — neither value over the threshold. 1,145 projects that used to
   get one sentence and no next step. */
.re-pd-goodbox {
    border: 1px solid var(--re-dash-success-line); background: var(--re-dash-success-soft);
    border-radius: var(--re-dash-control-radius); padding: 16px;
}
.re-pd-goodbox-title { font-weight: 700; font-size: 16px; color: var(--re-dash-success-darker); margin-bottom: 4px; }

/* The paid second report — informational blue, not the red of a problem.
   D51 made it GOOD NEWS ("AI Report is ready as well!"); the metrics follow
   the artifact's .paywait so the parity harness measures them equal. */
.re-pd-second-rep { border: 1px solid var(--re-dash-info-dark); border-radius: var(--re-dash-control-radius); overflow: hidden; margin: 12px 0; }
/* The head carries the text styles itself (the artifact's .pwh is one element)
   so the harness can measure head-for-head; the title div just inherits. */
.re-pd-second-rep-head {
    padding: 10px 13px; background: var(--re-dash-info-soft);
    border-bottom: 1px solid var(--re-dash-info-line);
    font-weight: 700; font-size: 13.5px; color: var(--re-dash-info-dark);
}
.re-pd-second-rep-title { font-weight: 700; font-size: 13.5px; color: var(--re-dash-info-dark); }
.re-pd-second-rep-body { padding: 12px 13px; }

/* ── Status messages / ledger / destructive actions ──────────────────────── */
.re-pd-statusmsg {
    border-left: 3px solid var(--re-dash-border); padding: 13px 15px;
    border-radius: 0 var(--re-dash-control-radius) var(--re-dash-control-radius) 0;
    background: var(--re-dash-bg-header);
}
.re-pd-statusmsg--hold { border-left-color: var(--re-dash-warning-dark); }
.re-pd-statusmsg--ref,
.re-pd-statusmsg--err  { border-left-color: var(--re-dash-danger-dark); }
.re-pd-statusmsg-t { font-weight: 700; font-size: 15px; margin-bottom: 4px; }

.re-pd-ledger { display: flex; flex-direction: column; border: 1px solid var(--re-dash-border); border-radius: var(--re-dash-control-radius); overflow: hidden; }
.re-pd-ledger > div { display: flex; justify-content: space-between; gap: 12px; padding: 11px 14px; border-bottom: 1px solid var(--re-dash-border-light); font-size: 13.5px; }
.re-pd-ledger > div:last-child { border-bottom: 0; }
.re-pd-ledger-v { font-weight: 600; font-variant-numeric: tabular-nums; }

.re-pd-gatehint { font-size: 11.5px; color: var(--re-dash-fg-muted); margin-top: 7px; }

/* D53 — an action mentioned INSIDE a sentence, where a button would break the
   line ("Submit the document again any time to run a fresh check"). The
   artifact's .linkact: quiet underlined text, never a standalone control. */
.re-pd-linkact {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 13px; color: var(--re-dash-fg-secondary); text-decoration: none;
    border-bottom: 1px solid var(--re-dash-border); padding-bottom: 1px;
}
.re-pd-linkact:hover,
.re-pd-linkact:focus {
    color: var(--re-dash-fg); text-decoration: none;
    border-bottom-color: var(--re-dash-fg-secondary);
}
/* The one-way-forward sentence under the "files deleted" box centres like the
   other captions at the deliverable card's foot. */
.re-pd-deliver .re-pd-removed + .re-pd-gatehint {
    text-align: center; max-width: 56ch; margin-left: auto; margin-right: auto;
}

/* ── Trust strip in a card ───────────────────────────────────────────────── */
/* Same component as the public service page. Inside a card it stacks, because
   the card is narrow — the strip's own min-width already does that below 767px. */
.re-pd-trust .re-trust-item { flex: 1 1 100%; }
.re-pd-trust .re-trust-item + .re-trust-item { border-left: 0; border-top: 1px solid var(--re-dash-border-light); }

/* ── FAQ card ────────────────────────────────────────────────────────────── */
/* get_faq_card() hardcodes style="background-color: #cdd7e3" on its header — legacy
   screens keep it (design rollout goes one screen at a time); the stage pages flatten it.
   !important: only way past an inline style attribute. */
.re-pd .card > .card-header[style] { background-color: var(--re-dash-bg-header) !important; }
/* Rows flush with the card title, as the artifact draws them (.faq button
   padding 13px 0) — the helper's 20px side padding pushed every question in. */
.re-pd .rel-faq-accordion .accordion-msg { padding: 13px 0; }
/* The artifact's rows: a hairline between them, and an open row that only flips
   + to − with the answer as plain text under it. jQuery UI paints the open header
   AdminDek's primary blue and the helper prints Bootstrap's `border
   border-primary pt-3` on the answer — utility classes that carry !important, which is
   the only reason the answer rule below needs it. */
.re-pd .rel-faq-accordion .accordion-msg { border-bottom: 1px solid var(--re-dash-border-light); }
.re-pd .rel-faq-accordion .accordion-msg.ui-state-active,
.re-pd .rel-faq-accordion .accordion-msg.ui-accordion-header-active { background: none; color: var(--re-dash-fg); border-bottom-color: transparent; }
/* !important: get_faq_card() writes Bootstrap's `border border-primary pt-3` utilities on
   the answer, which are !important themselves; legacy screens keep them (rollout rule). */
.re-pd .rel-faq-accordion .accordion-desc {
    border: 0 !important; border-bottom: 1px solid var(--re-dash-border-light) !important;
    background: none; box-shadow: none; padding: 0 0 13px !important; color: var(--re-dash-fg-secondary); font-size: 13.5px; line-height: 1.55;
}
.re-pd .rel-faq-accordion .accordion-desc * { color: inherit; }

/* The artifact draws a `+` at the right edge of every FAQ row, flipping to a
   minus while the row is open. get_faq_card()'s own affordance is a
   `zmdi zmdi-chevron-down` span — a Material Design Iconic glyph, and that
   icon font is loaded by no asset lane in either plugin, so the span renders
   zero-width and the row shows no affordance at all. accordion.js still swaps
   chevron-down for chevron-up on open, so the existing span is the state
   carrier: the glyph is drawn on it with `content`. Scoped to .re-pd — the
   legacy screens keep the helper's output exactly as it is. */
.re-pd .rel-faq-accordion .ui-accordion-header-icon { color: var(--re-dash-fg-muted); font-weight: 600; line-height: 1.4; }
/* TWO icon spans sit in each header: the helper prints one and jQuery UI's
   accordion() prepends its own. Only the first is drawn — both carry the same
   classes, so without the guard every row showed "++". */
.re-pd .rel-faq-accordion .ui-accordion-header-icon:first-child::before { content: '+'; }
.re-pd .rel-faq-accordion .zmdi-chevron-up:first-child::before { content: '\2212'; /* minus sign — same optical width as the + */ }
.re-pd .rel-faq-accordion .ui-accordion-header-icon:not(:first-child) { display: none; }

/* ── FAQ tag ─────────────────────────────────────────────────────────────── */
.re-pd-kbtag {
    font-size: 10.5px; color: var(--re-dash-fg-muted); background: var(--re-dash-bg-header);
    border: 1px solid var(--re-dash-border); border-radius: 4px; padding: 1px 6px;
}

/* ── Help block ──────────────────────────────────────────────────────────── */
/* D19. Which action LEADS is decided here, at 992px, and not by sniffing the
   user agent: below it WhatsApp is filled because the deep link opens the
   installed app; above it live chat leads, because wa.me on desktop opens
   WhatsApp Web and needs an already-paired session. Order, not visibility —
   every action stays reachable at every width. */
/* Help is never a primary action — the owner's rule, 2026-09-02: "the buttons
   for the need help do not need a primary secondary action". All three are mini
   outlines, and this block decides only which one comes FIRST. */
.re-pd-help-head { margin-bottom: 4px; }
.re-pd-help-btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.re-pd-help-wa { order: 1; }
.re-pd-help-call { order: 2; }
.re-pd-help-chat { order: 3; }
@media (min-width: 992px) {
    /* Below 992px the wa.me deep link opens the installed app, so WhatsApp
       leads. Above it, wa.me opens WhatsApp Web and needs an already-paired
       session, so live chat leads. Order, not visibility — every action stays
       reachable at every width. */
    .re-pd-help-chat { order: 0; }
}

/* Jimmy sits INSIDE the help card, not as a second bubble (D38 / D41). It is
   rendered only where the corner launcher would also render. */
.re-pd-jimmy {
    display: flex; align-items: center; gap: 9px; margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--re-dash-border-light);
}
.re-pd-jimmy-av {
    flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--re-dash-info-soft); color: var(--re-dash-info-dark); font-size: 12px;
}
.re-pd-jimmy-tx { flex: 1; min-width: 0; font-size: 12.5px; color: var(--re-dash-fg-secondary); }
.re-pd-jimmy-tx b { color: var(--re-dash-fg); font-weight: 600; }

/* ── App nudge ───────────────────────────────────────────────────────────── */
.re-pd-appnudge { display: flex; align-items: center; gap: 12px; }
.re-pd-appnudge-ico { font-size: 22px; color: var(--re-dash-fg-muted); }
.re-pd-appnudge-tx { flex: 1; min-width: 0; }
.re-pd-appnudge-t { display: block; font-weight: 600; font-size: 13.5px; }
.re-pd-appnudge-s { display: block; font-size: 12px; color: var(--re-dash-fg-muted); }
/* The store links are `btn btn-mini btn-outline-dark` (D46), as the artifact
   draws them — the mini's ::after hit area (scoped to .re-pd above) supplies the
   touch floor. This container only lays the pair out. */
.re-pd-appnudge-links { display: flex; gap: 6px; flex: 0 0 auto; }

/* ── Re-upload ───────────────────────────────────────────────────────────── */
/* get_submit_button_html() with btn_class `btn-mini btn-dark` (ruling D-D1):
   centre its column and sit its spinner inline instead of floated. */
.re-pd-upl { margin-top: 14px; }
.re-pd-upl .o-hidden { overflow: visible; text-align: center; padding-top: 12px; }
.re-pd-upl .fa-ajax-spinner { float: none; font-size: 14px; margin-right: 6px; vertical-align: middle; }

/* ── Stage rulings, 2026-10-15 (formatting family + shared shell) ────────── */
/* Drop zone (design s1 error, s3 ask) — shared by the re-upload form and the
   guidelines box. The real <input type=file> covers the whole tile at zero
   opacity, so a click AND a drag-and-drop both land on it with no script;
   my-account.js only writes the chosen file's name into the title. */
.re-pd-drop {
    position: relative; display: flex; flex-direction: column; align-items: center; gap: 4px;
    width: 100%; margin: 0; padding: 22px 16px; text-align: center; cursor: pointer;
    border: 1px dashed var(--re-dash-border); border-radius: var(--re-dash-control-radius);
    background: var(--re-dash-bg-header);
}
.re-pd-drop--sm { padding: 16px 14px; }
.re-pd-drop:hover { border-color: var(--re-dash-fg-muted); }
.re-pd-drop:focus-within { outline: 2px solid var(--re-dash-info); outline-offset: 1px; }
.re-pd-drop-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.re-pd-drop .fa { font-size: 18px; color: var(--re-dash-fg); }
.re-pd-drop-t { font-size: 14px; font-weight: 700; color: var(--re-dash-fg); overflow-wrap: anywhere; }
.re-pd-drop-k { font-size: 12px; color: var(--re-dash-fg-muted); }

/* Guidelines box, have state: title + value left, the one control right. The
   Change control is a <details>; its summary is lifted into the row so the form
   still opens full width beneath it. (.re-pd-gbox--have itself is declared once, above.) */
.re-pd-gbox-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.re-pd-gbox-main { flex: 1 1 auto; min-width: 0; }
.re-pd-gbox-act { flex: 0 0 auto; }
.re-pd-gbox-act .btn { padding: 4px 10px; font-size: 12px; line-height: 1.4; }
.re-pd-gbox-row--change { padding-right: 76px; }
.re-pd-gbox--have > .re-pd-gbox-change { margin-top: 0; }
.re-pd-gbox--have > .re-pd-gbox-change > summary { position: absolute; top: 30px; right: 14px; }
.re-pd-gbox--have > .re-pd-gbox-change[open] > .re-pd-gbox-form { margin-top: 12px; }

/* The muted, unlinked file name — the hub's rule for a file that cannot be
   downloaded (deleted, not yet paid for, closed project). */
.re-pd-fname--gone .copy-text { color: var(--re-dash-fg-muted); }

/* "✓ Your document is formatted" (design s5): the done mark beside the title. */
.re-pd-okhd { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.re-pd-okhd h5 { margin: 0; }
.re-pd-okhd-ic {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 50%;
    background: var(--re-dash-success-soft); color: var(--re-dash-success-darker); font-size: 14px;
}

/* The refunded screen's bank note, off the ledger's bottom edge. */
.re-pd .re-pd-ledger + .re-pd-muted { margin-top: 8px; }

/* "Delete my files" hint, centred under its button (design s6). */
.re-pd .re-pd-delhint { text-align: center; font-size: 12.5px; margin-bottom: 0; }

/* ── Spacing utilities ───────────────────────────────────────────────────── */
/* Two of them, deliberately. The design-system rule bans style="" in templates,
   and the alternative to a pair of spacing classes is a bespoke class per
   one-off gap — which is how a stylesheet grows a hundred single-use rules. */
/* Scoped, so they out-specify `.re-pd p { margin: 0 0 10px }` — the bare
   .re-pd-mt lost to it and the margin silently did nothing. */
.re-pd .re-pd-mt   { margin-top: 12px; }
.re-pd .re-pd-mt-0 { margin-top: 0; }
.re-pd .re-pd-mb-0 { margin-bottom: 0; }
.re-pd .re-pd-m-0  { margin: 0; }
.re-pd .re-pd-img  { width: 100%; height: auto; display: block; }

/* ── Referral card, stage variant only (D44) ─────────────────────────────── */
/* The link panel and the link carry NO green inside the stage view: the tinted
   panel and green link read as a promotion, and the referral link is a quiet
   utility the customer copies. Scoped to .re-pd — only the stage templates
   pass generate_referral_card()'s $compact flag, and they are the only screens
   inside .re-pd, so the dashboard and the legacy partial keep the full green
   card exactly as it is. Values are the artifact's .reflink. */
.re-pd .odr-refer-link {
    background: var(--re-dash-bg-header);
    border-color: var(--re-dash-border);
    padding: 10px 12px;
}
.re-pd .odr-refer-link-label {
    font-family: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
    font-weight: 400; letter-spacing: .08em;
}
.re-pd .odr-refer-link a {
    font-family: inherit; font-size: 12px; font-weight: 400;
    color: var(--re-dash-fg-secondary); word-break: break-all;
}
.re-pd .odr-refer-link a:hover,
.re-pd .odr-refer-link a:focus { color: var(--re-dash-fg); }

/* ── Third-party helper output rendered inside a stage ───────────────────── */
/* get_quotation_table() is shared with the legacy templates, so its own CSS
   cannot change. Inside the stage view its controls are lifted to the 44px
   tap-target floor — scoped to .re-pd so the old screens are untouched. The
   referral card used to be in this list; its stage variant is now compact
   (btn-mini + outline), and minis get their tap floor from the .btn-mini
   ::after rule above — 44px min-height would re-inflate them into slabs. */
.re-pd table + .text-center .btn { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }

/* ── Upload progress ─────────────────────────────────────────────────────── */
/* Driven by relFormSubmission()'s xhr.upload progress hook (omak-dash
   ajaxactions.js). Hidden until a submit starts; `is-processing` is the state
   after 100% of the bytes are sent but before the server has answered, which on
   a re-upload includes re-queueing the check. */
.re-pd-progress { margin-top: 12px; }
.re-pd-progress-track {
    height: 8px; border-radius: 4px; overflow: hidden;
    background: var(--re-dash-border);
}
.re-pd-progress-fill {
    display: block; height: 100%; width: 0;
    background: var(--re-dash-brand-dark);
    transition: width .15s linear;
}
.re-pd-progress-text { font-size: 12px; color: var(--re-dash-fg-secondary); margin-top: 6px; }
/* Bytes sent, but the server has not answered yet — a solid full bar would read
   as "finished". */
.re-pd-progress.is-processing .re-pd-progress-fill {
    width: 100% !important; /* beats the inline width the JS sets */
    background: linear-gradient(90deg, var(--re-dash-brand-dark) 0 40%, var(--re-dash-success-darker) 40% 100%);
    animation: rePdPulse 1.2s ease-in-out infinite;
}
/* Chunked request: the browser cannot say how many bytes there are in total, so
   the bar sweeps rather than inventing a number. */
.re-pd-progress.is-indeterminate .re-pd-progress-fill {
    width: 40% !important;
    animation: rePdSweep 1.1s ease-in-out infinite;
}
@keyframes rePdPulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@keyframes rePdSweep { 0% { margin-left: -40%; } 100% { margin-left: 100%; } }
@media (prefers-reduced-motion: reduce) {
    .re-pd-progress-fill { transition: none; animation: none !important; }
}

/* ── Fee calculator, embedded in a stage card ────────────────────────────── */
/* [odr_pr_costing_calc] renders its price table into .cal_result, which jQuery's
   slide animation leaves carrying an INLINE `overflow: hidden`. At 390px the
   table is 341px wide inside a 248px box, so 93px of the price the customer came
   to see is unreachable — no scrollbar, no page overflow, nothing that any other
   measurement notices.
   Fighting the inline style would need !important, so the table is made to FIT
   instead: full width, fixed layout, wrapping cells. Scoped to .re-pd because the
   shortcode is shared with the public site. */
.re-pd .cal_result table { width: 100%; min-width: 0; table-layout: fixed; }
.re-pd .cal_result th,
.re-pd .cal_result td { word-break: break-word; padding: 6px 8px; font-size: 12.5px; }

/* ── Numbered explanation (removal family, received) ─────────────────────── */
.re-pd-steps-list { margin: 0 0 14px; padding-left: 20px; }
.re-pd-steps-list li { font-size: 13.5px; color: var(--re-dash-fg-secondary); margin-bottom: 7px; line-height: 1.5; }
.re-pd-steps-list li::marker { color: var(--re-dash-fg-muted); font-weight: 700; }

/* ── Focus ───────────────────────────────────────────────────────────────── */
/* The audit found 20 tab stops on this page with no visible focus ring. */
.re-pd a:focus-visible,
.re-pd button:focus-visible,
.re-pd input:focus-visible,
.re-pd [tabindex]:focus-visible {
    outline: 2px solid var(--re-dash-info-dark);
    outline-offset: 2px;
}

/* ── Shared pay widget ───────────────────────────────────────────────────── */
/* create_pay_now_buttons() renders on six screens including /pay/, so both rules
   below are written to be safe everywhere and not scoped to .re-pd.
   Verification list: docs/user-view-rework/BUILD-PLAN.md. */

/* Stack on phones. The credits box and the pay button shared a row and the
   button ended up 96px wide at 360px. Desktop is untouched. */
@media (max-width: 575.98px) {
    .rel-pay-button-credits { flex-direction: column; align-items: stretch; gap: 12px; }
    .rel-pay-button-credits #rzp-button { width: 100%; min-height: 48px; }
}

/* Inside the stage view the widget lives in a 360px column at EVERY width, so it
   stacks there regardless of viewport — side by side, "Use Credits?" broke across
   three lines and the button lost half its label. Scoped to .re-pd; the other
   five call sites keep the row. */
.re-pd .rel-pay-button-credits { flex-direction: column; align-items: stretch; gap: 12px; }
.re-pd .rel-pay-button-credits #rzp-button { width: 100%; min-height: 48px; }
/* AdminDek's .btn-success is a turquoise that belongs to no other control on this
   page. Inside the stage view the primary action is the brand green, the same as
   every other primary action here. Scoped, so /pay/ and the legacy screens keep
   the button they have. */
.re-pd #rzp-button {
    background: var(--re-dash-brand-dark);
    border-color: var(--re-dash-brand-dark);
    color: var(--re-dash-fg-inverse);
    font-weight: 700;
    border-radius: var(--re-dash-control-radius);
}
.re-pd #rzp-button:hover,
.re-pd #rzp-button:focus { background: var(--re-dash-success-darker); border-color: var(--re-dash-success-darker); }
/* D62: the locked AI report is a second FILE in the deliverable pair, not a Pay slab, so it keeps
   the pair's outline look. The id rule above would otherwise paint it green. */
.re-pd #rzp-button.btn-outline-dark {
    background: transparent;
    border-color: var(--re-dash-fg);
    color: var(--re-dash-fg);
    font-weight: 600;
}
.re-pd #rzp-button.btn-outline-dark:hover,
.re-pd #rzp-button.btn-outline-dark:focus { background: var(--re-dash-fg); border-color: var(--re-dash-fg); color: var(--re-dash-fg-inverse); }
.re-pd .odr-credits-box__row { display: flex; align-items: center; gap: 6px; }

/* 44px hit area for the credits info button WITHOUT changing layout. min-height
   here would resize the widget on every service that renders it. */
.odr-credits-box__info-btn { position: relative; }
.odr-credits-box__info-btn::after { content: ''; position: absolute; inset: -15px; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE CUSTOMER DASHBOARD
   ═══════════════════════════════════════════════════════════════════════════
   The page is wrapped in `.re-pd` as well as `.re-dash`, so everything the
   customer project screens established — IBM Plex at 14/1.55, the button tiers,
   the card metrics, the sentence-case rule — applies here without a second
   system. These rules are only the parts this screen has and those do not.
   ═══════════════════════════════════════════════════════════════════════════ */

/* One notice slot. Three stacked full-width banners is not three times the
   message; it is one strip nobody reads. Tone by token, never a raw hex. */
.re-dash-notice {
    display: flex; align-items: flex-start; gap: 10px; padding: 11px 14px;
    border: 1px solid var(--re-dash-border); border-left-width: 3px;
    border-radius: var(--re-dash-control-radius);
    background: var(--re-dash-bg); font-size: 13px; margin-bottom: 10px;
}
.re-dash-notice + .re-dash-notice { margin-top: -2px; }
.re-dash-notice--warn { border-left-color: var(--re-dash-warning-dark); background: var(--re-dash-warning-soft); }
.re-dash-notice--info { border-left-color: var(--re-dash-info-dark); background: var(--re-dash-info-soft); }
.re-dash-notice > span:first-child { flex: 1; min-width: 0; }
.re-dash-notice .close { font-size: 20px; line-height: 1; opacity: .5; background: none; border: 0; padding: 0 2px; }
.re-dash-notice .close:hover { opacity: 1; }

.re-dash-head { margin: 4px 0 14px; }
.re-dash-hi { font-family: 'Quicksand', ui-rounded, system-ui, sans-serif; font-weight: 700; font-size: 22px; margin: 0; }

/* ── "Needs you" ─────────────────────────────────────────────────────────── */
/* The most valuable block on the page: every row is a project whose next move
   belongs to the customer, and 886 of those across the corpus are unpaid. */
.re-dash-att-row {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 0; border-bottom: 1px solid var(--re-dash-border-light);
}
.re-dash-att-row:last-child { border-bottom: 0; padding-bottom: 0; }
.re-dash-att-row:first-child { padding-top: 0; }
.re-dash-att-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--re-dash-border); }
.re-dash-att-dot--ready { background: var(--re-dash-warning-dark); }
.re-dash-att-dot--err   { background: var(--re-dash-danger-dark); }
.re-dash-att-dot--hold  { background: var(--re-dash-warning-dark); }
.re-dash-att-dot--done  { background: var(--re-dash-success-darker); }
.re-dash-att-main { flex: 1; min-width: 0; }
.re-dash-att-what { font-weight: 600; font-size: 13.5px; }
.re-dash-att-meta { font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 1px; }

/* ── Recent projects ─────────────────────────────────────────────────────── */
/* The action button used to be clipped off the right edge of every row: the
   list item was a nowrap flex with an absolutely-sized action. It wraps now,
   and the action sits under the title on a narrow column instead of leaving. */
.re-dash-recent-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.re-dash-recent .list-group-item {
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
    padding: 10px 0; border: 0; border-bottom: 1px solid var(--re-dash-border-light); background: none;
}
.re-dash-recent .list-group-item:last-child { border-bottom: 0; }
.re-dash-recent .list-group-item > * { min-width: 0; }
.re-dash-recent .list-group-item .btn { white-space: normal; }

/* ── Credits ─────────────────────────────────────────────────────────────── */
.re-dash-bal {
    font-family: 'Quicksand', ui-rounded, system-ui, sans-serif;
    font-weight: 700; font-size: 26px; line-height: 1.1; margin-bottom: 6px;
    font-variant-numeric: tabular-nums;
}

/* ── The service chooser ─────────────────────────────────────────────────── */
/* Thirteen brochure cards became thirteen lines. The copy still exists — on the
   public service pages these link to, where it was written to sell. */
.re-dash-svc-item {
    display: block; padding: 11px 12px; border: 1px solid var(--re-dash-border);
    border-radius: var(--re-dash-control-radius); margin-bottom: 10px;
    text-decoration: none; height: calc(100% - 10px);
}
.re-dash-svc-item:hover, .re-dash-svc-item:focus {
    border-color: var(--re-dash-fg-secondary); text-decoration: none;
}
/* The bare `a` rule in the bundle paints every link #37474f; the chooser tile is
   a link but its words are body copy, so the colour is stated here rather than
   inherited from AdminDek. */
.re-dash-svc-item { color: var(--re-dash-fg-secondary); }
.re-dash-svc-name { display: block; font-weight: 600; font-size: 13.5px; color: var(--re-dash-fg); }
.re-dash-svc-line { display: block; font-size: 12px; color: var(--re-dash-fg-muted); margin-top: 2px; }

/* ── .odr-act: two owners, one class name ────────────────────────────────── */
/* `.pcoded-content .odr-act` is declared TWICE in this stylesheet with
   incompatible meanings: at ~483 it is the projects-list action cell (a wrapping
   flex row of buttons) and at ~1123 it is a 30x30 icon button for the users and
   offers tables. Same specificity, so the later one wins everywhere — which is
   why the customer's "Pay 149 to get report" button hung outside the card on the
   dashboard, forced into a 30px box.
   The projects list is the one that loses, so it is named more specifically
   here. The proper fix is to rename one of the two; that is a rename across
   several tables and belongs in its own change. */
.pcoded-content .odr-projects .odr-act {
    position: static; display: flex; flex-wrap: wrap; align-items: center;
    justify-content: flex-end; gap: 6px;
    width: auto; height: auto; border-radius: 0; background: none;
    max-width: 100%;
}
.pcoded-content .odr-projects .odr-act:hover { background: none; }
.pcoded-content .odr-projects .odr-act .btn { white-space: normal; max-width: 100%; }
/* The recent-projects card is narrow (5 of 12 columns), so a row that wants to
   wrap must be allowed to: the id and service take the first line, the status
   and the action the second. */
.re-dash-recent .odr-projects .list-group-item { padding-left: 0; padding-right: 0; }
.re-dash-recent .odr-projects .odr-act { justify-content: flex-start; }

/* One line, no actions — "we are working on it". Deliberately quieter than the
   attention card above it: nothing here is the customer's move. */
.re-dash-inflight .card-block { display: flex; align-items: center; gap: 11px; padding: 12px 16px; }
.re-dash-inflight-ico {
    flex: 0 0 30px; width: 30px; height: 30px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--re-dash-info-soft); color: var(--re-dash-info-dark); font-size: 13px;
}
.re-dash-inflight-tx { flex: 1; min-width: 0; font-size: 13px; color: var(--re-dash-fg-secondary); }
.re-dash-inflight-tx b { color: var(--re-dash-fg); font-weight: 600; }

/* Standing: three facts and two ways in. Not a chart — three payments do not
   make a trend line. */
.re-dash-stand-grid { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 32px; }
.re-dash-stand-n {
    font-family: 'Quicksand', ui-rounded, system-ui, sans-serif; font-weight: 700;
    font-size: 20px; line-height: 1.1; font-variant-numeric: tabular-nums;
}
.re-dash-stand-k { font-size: 11.5px; color: var(--re-dash-fg-muted); margin-top: 2px; }
.re-dash-stand-act { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px; }
@media (max-width: 575.98px) {
    .re-dash-stand-grid { gap: 12px 24px; }
    .re-dash-stand-act { margin-left: 0; width: 100%; }
}

/* Quick links — the five screens that only existed in the left rail, where the
   interesting ones sit below twelve service links. Navigation, so never filled. */
.re-dash-quick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/* First run: a deliberate screen, not the absence of one. */
.re-dash-fr-title { font-size: 17px; }
.re-dash-fr-steps { margin: 12px 0 12px 18px; padding: 0; font-size: 13.5px; }
.re-dash-fr-steps li { margin-bottom: 7px; color: var(--re-dash-fg-secondary); }
.re-dash-fr-steps li b { color: var(--re-dash-fg); font-weight: 600; }

/* Proof: one line, under the form it supports. Not a band of logos. */
.re-dash-proof {
    font-size: 12px; color: var(--re-dash-fg-muted); text-align: center;
    margin: 2px 0 14px;
}
/* The profile ask is the quietest notice on the page — it is our request, not
   the customer's task, so it never borrows the warning or info tone. */
.re-dash-notice--plain { background: var(--re-dash-bg); border-left-color: var(--re-dash-border); align-items: center; }
.re-dash-notice--plain .btn { flex: 0 0 auto; }
.re-dash-help { margin-top: 4px; }

/* Six questions as links, not thirty as an accordion. The answers live in the
   Help Centre; the dashboard's job is to point at them. */
.re-dash-faq { list-style: none; margin: 0; padding: 0; }
.re-dash-faq li { border-bottom: 1px solid var(--re-dash-border-light); }
.re-dash-faq li:last-child { border-bottom: 0; }
.re-dash-faq a {
    display: block; padding: 9px 0; font-size: 13.5px;
    color: var(--re-dash-fg-secondary); text-decoration: none;
}
.re-dash-faq a:hover, .re-dash-faq a:focus { color: var(--re-dash-fg); text-decoration: none; }

/* In the narrow recent-projects column a pay button needs the whole width more
   often than not; letting it stretch beats letting it hang off the card. */
@media (min-width: 992px) {
    .re-dash-recent .odr-projects .odr-act { width: 100%; }
    .re-dash-recent .odr-projects .odr-act .btn { flex: 1 1 auto; justify-content: center; }
}

/* The recent-projects actions come from get_action_html() as `btn btn-sm` —
   34px tall, under the 44px tap floor the audit measured. Same pseudo-element
   hit area the mini buttons use: the target grows, the layout does not move.
   Scoped to the dashboard's project list so no admin table is affected. */
.re-dash-recent .odr-projects .btn-sm { position: relative; }
.re-dash-recent .odr-projects .btn-sm::after { content: ''; position: absolute; inset: -5px -4px; }
/* Six services on a phone, the rest behind one control. Desktop shows them all:
   three to a row is 5 rows, which is not a wall. */
.re-dash-svc-toggle { display: none; }
@media (max-width: 767.98px) {
    .re-dash-svc-more { display: none; }
    .re-dash-svc.is-open .re-dash-svc-more { display: block; }
    .re-dash-svc-toggle { display: block; margin-top: 4px; }
}

/* ── Dashboard, second wave ──────────────────────────────────────────────── */
/* Files the customer has paid for, one click from the front page. */
.re-dash-file-row {
    display: flex; align-items: center; gap: 10px; padding: 9px 0;
    border-bottom: 1px solid var(--re-dash-border-light);
    font-size: 13.5px; color: var(--re-dash-fg); text-decoration: none;
}
.re-dash-file-row:last-child { border-bottom: 0; }
.re-dash-file-row:hover, .re-dash-file-row:focus { color: var(--re-dash-brand-dark); text-decoration: none; }
.re-dash-file-label { flex: 1; min-width: 0; font-weight: 600; }
.re-dash-file-pid { font-family: 'IBM Plex Mono', ui-monospace, Menlo, monospace; font-size: 11px; color: var(--re-dash-fg-muted); }

/* What it costs — two services, a floor price and a turnaround. */
.re-dash-price-row {
    display: flex; align-items: baseline; gap: 10px; padding: 8px 0;
    border-bottom: 1px solid var(--re-dash-border-light); font-size: 13.5px;
}
.re-dash-price-svc { flex: 1; min-width: 0; font-weight: 600; }
.re-dash-price-fee { font-variant-numeric: tabular-nums; }
.re-dash-price-tat { font-size: 11.5px; color: var(--re-dash-fg-muted); white-space: nowrap; }

/* Activity: what happened, in the customer's words. */
.re-dash-act-row {
    display: flex; align-items: baseline; gap: 10px; padding: 7px 0;
    border-bottom: 1px solid var(--re-dash-border-light); font-size: 13px;
}
.re-dash-act-row:last-child { border-bottom: 0; }
.re-dash-act-what { flex: 1; min-width: 0; color: var(--re-dash-fg-secondary); }
.re-dash-act-when { font-size: 11.5px; color: var(--re-dash-fg-muted); white-space: nowrap; }
.re-dash-act-pid { font-family: 'IBM Plex Mono', ui-monospace, Menlo, monospace; font-size: 11px; color: var(--re-dash-fg-muted); }

/* One customer's words, next to the form. Quiet: it supports the decision, it
   does not make it. */
.re-dash-quote {
    margin: 12px 0 0; padding: 12px 14px; border-left: 3px solid var(--re-dash-border);
    background: var(--re-dash-bg-header); border-radius: 0 var(--re-dash-control-radius) var(--re-dash-control-radius) 0;
}
.re-dash-quote p { font-size: 13px; color: var(--re-dash-fg-secondary); margin: 0 0 6px; font-style: italic; }
.re-dash-quote footer { font-size: 11.5px; color: var(--re-dash-fg-muted); }

.re-dash-repeat { font-size: 13px; color: var(--re-dash-fg-secondary); margin: 12px 0 0; }
.re-dash-refprog { font-size: 12.5px; color: var(--re-dash-fg-secondary); margin: 8px 2px 0; }
.re-dash-invoice {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    font-size: 12.5px; color: var(--re-dash-fg-secondary); margin: 10px 2px 0;
}
.re-dash-invoice > span { flex: 1; min-width: 0; }

/* Full width now that pricing moved into the left column: three promises in a
   row rather than a tall stack in a narrow one. */
@media (min-width: 768px) {
    .re-dash .card > .re-trust-strip { display: flex; }
    .re-dash .card > .re-trust-strip .re-trust-item { flex: 1 1 0; border-top: 0; }
    .re-dash .card > .re-trust-strip .re-trust-item + .re-trust-item {
        border-left: 1px solid var(--re-dash-border-light); border-top: 0;
    }
}

/* ── Parity with the design file (dash-parity.js) ────────────────────────── */
/* Every rule here closes a measured difference between
   docs/user-view-rework/design/customer-dashboard.html and the built page.
   AdminDek's card chrome is what they all come from. */
.re-dash .card > .card-header { border-radius: 0; }
/* The design gives the body a flat 16px and lets the head carry the 14px above
   it; the earlier 14px top here made every card 2px tighter than drawn. */
.re-dash .card > .card-header + .card-block { padding-top: 16px; }
/* AdminDek's card heading is #333 on a 1.1 leading in a two-family stack. */
.re-dash .card > .card-header h5 {
    font-family: 'Quicksand', ui-rounded, system-ui, sans-serif;
    line-height: 1.55;
    color: var(--re-dash-fg);
}
.re-dash-quote { font-size: 12.5px; }

/* ── Settings → Jimmy (view-settings-jimmy.php) ──────────────────────────── */
/* Only spacing and the read-only engine rows; every colour is a --re-dash-* token,
   and the controls themselves are AdminDek's own card / input-group / table. */
.odr-jimmy-sub { display: block; font-size: 13px; line-height: 1.55; margin-top: 4px; }
.odr-jimmy-heading { color: var(--re-dash-card-header); font-weight: 600; margin-bottom: 6px; }
.odr-jimmy-note { border-radius: var(--re-dash-control-radius); font-size: 13px; line-height: 1.6; }
.odr-jimmy-table td { vertical-align: middle; }
.odr-jimmy-resume { display: inline-block; margin: 0; }
.odr-jimmy-resume .ajax-result:empty { display: none; }
.odr-jimmy-readonly {
    display: flex; justify-content: space-between; gap: 16px;
    padding: 9px 0; border-bottom: 1px dashed var(--re-dash-border-light); font-size: 13.5px;
}
.odr-jimmy-readonly:last-of-type { border-bottom: 0; }
.odr-jimmy-readonly .k { color: var(--re-dash-fg-secondary); }
.odr-jimmy-readonly .v {
    color: var(--re-dash-fg); font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12.5px; text-align: right; word-break: break-all;
}

/* ==========================================================================
 * Settings screens (RE Settings, Pricing & Payments, Developer) — drawn from the
 * settings registry by rel_settings_render_screen(). Owner, 2026-09-26.
 * Card bodies start closed (AdminDek's title toggles them); the description
 * lives inside the body, never in the header.
 * ======================================================================== */
.rel-settings-card-body { display: none; }
.rel-settings-card-desc { color: var(--re-dash-fg-secondary); margin: 0 0 12px; max-width: 75ch; }
.rel-settings-head { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 12px; }
.rel-settings-tabs { flex: 1 1 auto; border-bottom: 0; }
.rel-settings-search { position: relative; flex: 1 1 320px; max-width: 520px; }
.rel-settings-search .fa-search { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--re-dash-fg-placeholder); pointer-events: none; }
.rel-settings-search input { padding-left: 32px; }
.rel-settings-results { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 1030; max-height: 360px; overflow: auto;
    background: var(--re-dash-bg); border: 1px solid var(--re-dash-border); border-radius: 6px; }
.rel-settings-results a { display: block; padding: 8px 12px; border-bottom: 1px solid var(--re-dash-border-light); color: var(--re-dash-fg); }
.rel-settings-results a:hover,
.rel-settings-results a.is-active { background: var(--re-dash-bg-row-hover); text-decoration: none; }
.rel-settings-results .rel-settings-where { display: block; font-size: 12px; color: var(--re-dash-fg-muted); }
.rel-settings-results .rel-settings-none { padding: 10px 12px; color: var(--re-dash-fg-muted); }
.rel-setting.is-flash,
.rel-setting-block.is-flash { background: var(--re-dash-success-soft); transition: background .6s; }
.rel-secret-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 6px; }
.rel-secret-tools code { word-break: break-all; }
.rel-settings-block-note { color: var(--re-dash-fg-muted); }

/* ── Legacy advance-awaited page (parts/project-details-pr-advance-awaited.php) ─ */
/* Still reached by services without a stage page (Grammar Correction). Moved from
   the partial's inline <style> (2026-10-15); colours are tokens now. */
.ock-secondary { margin-top: 8px; }
.ock-testimonials { background: var(--re-dash-bg); border: 1px solid var(--re-dash-border); border-radius: 14px; overflow: hidden; margin-top: 8px; }
.ock-testimonials-header { padding: 16px 20px; border-bottom: 1px solid var(--re-dash-border-light); background: var(--re-dash-bg-header); }
.ock-testimonials-header h5 { margin: 0; font-size: 1.05rem; font-weight: 700; color: var(--re-dash-fg); }
.ock-testimonials-header small { color: var(--re-dash-fg-secondary); }
@media (max-width: 576px) {
    .ock-secondary { margin-top: 4px; }
    .ock-secondary .row > [class*="col-"] { margin-bottom: 10px !important; } /* beats the columns' mb-3 utility, which is !important */
    .ock-testimonials { border-radius: 12px; margin-top: 4px; }
    .ock-testimonials-header { padding: 12px 14px; }
    .ock-testimonials-header h5 { font-size: .95rem; }
    .ock-testimonials-header small { font-size: .72rem; }
}
