/* ============================================================================
   Lasso Media — v2 Theme  (purely presentational re-skin)
   ----------------------------------------------------------------------------
   ADDITIVE + SAFE. Loaded LAST so it wins the cascade.
   Three layers:
     1. :root design tokens (global)
     2. Base body look (global, low-risk)
     3. Global NAV — everything prefixed `lz-` so it can NEVER collide
        with Bootstrap 4.6's .navbar / .nav / .dropdown classes.
     4. Component library — every rule scoped under `.lasso-v2` so converted
        pages opt in and un-converted pages keep Bootstrap's identically
        named .btn / .card / .badge / table styling untouched.
   NO nuclear reset. The only reset (box-sizing) is scoped under .lasso-v2.
   Hex / radius / spacing values are copied verbatim from
   resources/new-designs/design-system.html.
   ========================================================================== */

/* 1 ── TOKENS ────────────────────────────────────────────────────────────── */
:root{
  --brand-red:#E8362B; --brand-red-dark:#C42A20; --ink:#22262B; --teal:#17A2B8;
  --teal-dark:#128294; --green:#1F9D57; --amber:#E8912B; --blue:#2F6FD6;
  --violet:#6C5CE7; --text:#2A2E33; --muted:#6B7480; --line:#E4E7EB;
  --bg:#F4F6F8; --white:#fff; --radius:14px;
  --card-shadow:0 1px 2px rgba(20,25,35,.06),0 6px 18px rgba(20,25,35,.05);

  /* ---- CONTENT WIDTH ----------------------------------------------------
     App pages under the v2 shell run FULL WIDTH with --lm-gutter down each side;
     the topbar, nav, body and footer all sit on that one edge.

     --lm-maxw is the centred-column width, used only by the auth pages
     (login / register), which render through layout_lasso_website. A 1240px
     column was tried across the whole app on 2026-08-17 and reverted the same
     day — these pages are dense (three-way wizard steps, 1500px list tables,
     side-by-side dashboard charts) and the cap congested exactly the screens it
     was meant to tidy. Exempting a few of them only made the app look
     inconsistent from one screen to the next.

     Reference: resources/new-designs/completed/package-wide-alignment-demo.html
     — its rule that bands run edge to edge while their contents share one left
     edge still holds; only the cap on that content was dropped. */
  --lm-maxw:1240px;
  --lm-gutter:32px;
}

/* 2 ── BASE LOOK (global, safe) ──────────────────────────────────────────── */
body{
  font-family:'Inter',system-ui,-apple-system,'Segoe UI',sans-serif;
  background:var(--bg);
  color:var(--text);
  -webkit-font-smoothing:antialiased;
}

/* ============================================================================
   3 ── GLOBAL NAVIGATION  (lz- prefix)
        Black top bar (--ink) + red nav strip (--brand-red)
        with a white active underline. Mirrors the design-system nav demo.
   ========================================================================== */

/* --- black top bar ------------------------------------------------------- */
/* One page gutter, 32px, shared by the logo, the nav links and the page body
   below them, so all three sit on a single left edge and move together as the
   window narrows. `main.lv2-main` already carries 32px, so that is the number
   the header matches — not the other way round. */
.lz-topbar{
  background:var(--ink);
  display:flex; align-items:center; gap:14px;
  padding:12px var(--lm-gutter);
  flex-wrap:wrap;
}
.lz-brand{
  display:inline-flex; align-items:center; gap:10px;
  text-decoration:none; line-height:1;
}
.lz-brand:hover{ text-decoration:none; }
/* The real client logo — /img/logos/Lasso-Logo-2025.png (768x288, 2.67:1).
   White wordmark on transparent, sized for the black .lz-topbar. The artwork
   already contains the "LOCAL. CONVERSION. MARKETING." tagline — do NOT add a
   separate CSS tagline beside it (see the archived block below). */
.lz-brand-img{ height:54px; width:auto; display:block; flex:none; }
@media(max-width:991px){ .lz-brand-img{ height:42px; } }

/* ARCHIVED 2026-07-15 — the v2 re-skin (733fea19e) dropped the real logo image and
   substituted this hand-drawn SVG pin + CSS text lockup. It was never what the client
   wanted, and it is what prompted 0afb7ef6a to re-add a tagline in CSS that the real
   artwork already had. Kept commented rather than deleted, per the archive-don't-delete
   rule. If you resurrect this, delete .lz-brand-img above first — not both.

.lz-brand svg{ width:30px; height:33px; flex:none; display:block; }
.lz-brand-word{ display:inline-flex; flex-direction:column; line-height:1; }
.lz-brand-lockup{
  font-family:'Montserrat','Inter',sans-serif; font-weight:900;
  color:#fff; font-size:18px; letter-spacing:.02em; line-height:1;
  white-space:nowrap;
}
.lz-brand-lockup span{
  color:#C7CCD2; font-weight:600; font-size:11px;
  letter-spacing:.24em; margin-left:6px;
}
.lz-brand-tag{
  font-style:normal; font-weight:700; font-size:8px; letter-spacing:.2em;
  color:#DDE1E6; display:block; margin-top:5px; padding-top:5px;
  border-top:1px solid rgba(255,255,255,.22); white-space:nowrap;
}
@media(max-width:991px){ .lz-brand-tag{ display:none; } }
*/
.lz-user{
  margin-left:auto; display:flex; align-items:center; gap:10px;
  color:#fff; font-size:13.5px; font-weight:700; flex-wrap:wrap;
}
.lz-user a{ color:#fff; text-decoration:none; font-weight:700; }
.lz-user a:hover{ color:#fff; text-decoration:underline; }

/* --- red nav strip ------------------------------------------------------- */
.lz-navstrip-wrap{
  background:var(--brand-red);
  color:#fff;
}
/* The strip sat flush at 0, which put "Home" to the LEFT of the logo. The nav
   links carry 14px of their own padding, so the container gets 32 - 14 = 18px
   and the first link's text lands on the shared 32px gutter.
   Qualified with #myHeader because lasso-v2-layout.css zeroes `.container-fluid`
   padding at equal specificity and loads later. */
/* 14px less than the shared column edge, because each nav link carries 14px of
   its own padding — that is what lands the FIRST LINK'S TEXT on the same edge as
   the logo above it and the page heading below, rather than the link's invisible
   padding box. */
#myHeader .lz-navstrip-wrap > .container-fluid{ padding-left:18px; padding-right:18px; }
/* `.lasso-v2 .row` carries a 12px gap. On mobile the collapsed #mobileNav is a
   second, zero-height flex line, so that gap rendered as 12px of dead red under
   the hamburger — the icon read as stuck to the top of the strip with a band of
   empty colour below it. The strip's children carry their own padding, so the
   row needs no gap of its own. ID-qualified to beat `.lasso-v2 .row` (0,2,0). */
#myHeader .lz-navstrip-wrap .row{ gap:0; }
/* the <ul> that holds the primary links */
.lz-navstrip{
  list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; align-items:stretch; gap:2px;
}
.lz-navstrip li{ list-style:none; }
/* link chrome (works for flat CPORTAL links AND admin dropdown toggles) */
.lz-navstrip a,
.lz-navstrip .lz-navlink{
  display:flex; align-items:center;
  color:#fff; text-decoration:none;
  font-family:'Inter',system-ui,sans-serif;
  font-size:13.5px; font-weight:600;
  padding:13px 14px;
  opacity:.88; position:relative; white-space:nowrap;
  background:transparent; border:0;
}
.lz-navstrip a:hover,
.lz-navstrip a:focus,
.lz-navstrip .lz-navlink:hover{ opacity:1; color:#fff; text-decoration:none; }
/* dev_header's LOGS counter / clock / release badge sit in the same strip and
   should read at the same size as the links beside them. Global, not
   .lasso-v2-scoped, because this nav is shared by every layout. */
.lz-partner .navbar-nav .nav-link{
  font-family:'Inter',system-ui,sans-serif; font-size:13.5px; font-weight:600;
}
/* active underline */
.lz-navstrip a.active,
.lz-navstrip li.active > a,
.lz-navstrip li.show > a{ opacity:1; }
.lz-navstrip a.active::after,
.lz-navstrip li.active > a::after{
  content:""; position:absolute; left:14px; right:14px; bottom:0;
  height:3px; background:#fff; border-radius:3px 3px 0 0;
}

/* --- admin mega-menu dropdowns (piggy-backs Bootstrap dropdown JS) ------- */
.lz-navstrip .lz-dropdown{ position:static; }           /* let panel span wide */
.lz-navstrip .lz-dropdown-toggle::after{                 /* tint the caret     */
  margin-left:.4em; vertical-align:middle; opacity:.85;
}
.lz-dropdown-panel{
  background:#fff; color:var(--text);
  border:1px solid var(--line);
  border-top:3px solid var(--brand-red);
  border-radius:0 0 12px 12px;
  box-shadow:var(--card-shadow);
  padding:18px 22px; margin-top:0;
  min-width:260px; max-width:min(1120px,96vw);
}
.lz-menu-grid{ display:flex; flex-wrap:wrap; gap:4px 30px; }
.lz-menu-col{ min-width:210px; padding-bottom:10px; }
.lz-menu-header{
  font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); padding:2px 0 8px; margin-bottom:6px;
  border-bottom:1px solid var(--line);
}
/* NB: prefixed with .lz-dropdown-panel so specificity (0,2,0) beats the
   red-strip link rule `.lz-navstrip a` (0,1,1) — otherwise panel items
   would inherit the strip's white text and vanish on the white panel. */
.lz-dropdown-panel .lz-menu-item{
  display:block; color:var(--text); text-decoration:none;
  font-size:13px; padding:6px 8px; border-radius:8px; opacity:1;
}
.lz-dropdown-panel .lz-menu-item:hover,
.lz-dropdown-panel .lz-menu-item:focus{
  background:var(--bg); color:var(--brand-red-dark); text-decoration:none;
}

/* --- partner logo + dev header slot on the strip ------------------------- */
.lz-partner{
  display:flex; align-items:center; justify-content:flex-end;
  gap:10px; color:#fff; font-weight:700; letter-spacing:1px;
}
.lz-partner img{ max-height:34px; width:auto; }

/* --- mobile hamburger ---------------------------------------------------- */
/* 14px of side padding — the same figure the desktop nav links carry — so the
   glyph lands on the shared 32px page gutter (18px container + 14px) as the
   logo above it does, instead of 4px inside it. 11px vertical makes the button
   a 44px touch target, matching the desktop strip's height. */
.lz-navtoggle{
  display:none; background:transparent; border:0; color:#fff;
  font-size:22px; line-height:1; padding:11px 14px; cursor:pointer;
}
.lz-navtoggle:focus{ outline:none; }

@media (max-width:991.98px){
  .lz-navtoggle{ display:inline-flex; align-items:center; }
  .lz-navstrip{ flex-direction:column; width:100%; gap:0; }
  .lz-navstrip a.active::after{ display:none; }
  .lz-navstrip a.active{ background:rgba(255,255,255,.14); }
  /* collapsed Bootstrap dropdowns render inline on mobile */
  .lz-dropdown-panel{
    position:static !important; width:100% !important;
    transform:none !important; box-shadow:none; border:0;
    border-top:1px solid rgba(255,255,255,.25); border-radius:0;
    background:transparent; color:#fff; padding:6px 14px 12px;
  }
  .lz-menu-grid{ flex-direction:column; gap:0; }
  .lz-menu-header{ color:rgba(255,255,255,.85); border-bottom-color:rgba(255,255,255,.2); }
  .lz-dropdown-panel .lz-menu-item{ color:#fff; }
  .lz-dropdown-panel .lz-menu-item:hover,
  .lz-dropdown-panel .lz-menu-item:focus{ background:rgba(255,255,255,.12); color:#fff; }
  .lz-partner{ justify-content:flex-start; padding:6px 14px; }
  /* the mobile-only account block under the links — same 14px the links carry,
     so it lines up with them instead of sitting 14px further left */
  #mobileNav .lz-user{ padding:0 14px 10px; }
}

/* ============================================================================
   4 ── COMPONENT LIBRARY  — everything scoped under `.lasso-v2`
        Mirrors design-system.html class names so mockup markup can be
        pasted into converted pages with minimal edits.
   ========================================================================== */
.lasso-v2 *{ box-sizing:border-box; }

.lasso-v2{ font-family:'Inter',system-ui,sans-serif; color:var(--text); }

/* layout */
.lasso-v2 .container{ max-width:1080px; margin:0 auto; padding:40px 32px 80px; }
/* Dashboard body: left-aligned to the shared page gutter rather than centred in
   a 1080 column, so it shares an edge with the logo and nav above it. The 32px
   gutter is already on `main.lv2-main`, so this adds none of its own. The width
   cap stays (1180, per the dashboard redesign) — it just no longer centres, so
   the cards do not sprawl on a very wide monitor. */
/* Tightened 2026-08-17: 40px of lead-in above the greeting pushed the package CTA
   below the fold on a 1080px screen. */
.lasso-v2 .container.dash-container{ max-width:1180px; margin:0; padding:22px 0 60px; }
.lasso-v2 .row{ display:flex; gap:12px; flex-wrap:wrap; align-items:center; }
/* `align-items:center` above is right for the in-cell button rows this theme was
   built around, but wrong for GRID rows: two columns of unequal height end up
   centered against each other, so the shorter column floats down the page (it
   pushed the form on Lasso Big Boards' edit page ~450px below its sibling, and
   the left table on the HNC geo-target summary well below the right one).
   Bootstrap grid columns should top-align, so opt them out — except in rows that
   explicitly ask for centering (the nav's `.row.align-items-center`, the search
   toolbar's `.row.underline`, the pager), which stay as they are.
   A row of equal-height cards must opt out with `.align-items-stretch` —
   `align-items:stretch` on the row alone cannot win, because align-self on the
   item always beats align-items on the container. */
/* `align-items-end` / `-baseline` join the opt-out list: this sets align-self on
   the CHILD, which beats any align-items the row sets on itself, so without them
   a row asking to bottom-align was overruled one level down. */
.lasso-v2 .row:not(.align-items-center):not(.align-items-stretch):not(.align-items-end):not(.align-items-baseline):not(.underline):not(.lasso-pager) > [class*="col-"]{ align-self:flex-start; }
.lasso-v2 .align-items-stretch{ align-items:stretch; }
.lasso-v2 .row.align-items-stretch > [class*="col-"]{ align-self:stretch; }
.lasso-v2 .cards3{ display:grid; grid-template-columns:repeat(3,1fr); gap:16px; }
@media(max-width:720px){ .lasso-v2 .cards3{ grid-template-columns:1fr; } }

/* The step the user is on right now. Used on the "what happens next" cards so
   the one they should act on is not just first in reading order. */
.lasso-v2 .card.is-current{ border-color:var(--brand-red); box-shadow:0 0 0 3px rgba(232,54,43,.12); position:relative; }
.lasso-v2 .card.is-current .step-now{
  display:inline-flex; align-items:center; gap:6px; background:#FDECEA; color:var(--brand-red);
  font-weight:800; font-size:10.5px; letter-spacing:.1em; text-transform:uppercase;
  padding:4px 10px; border-radius:999px; margin-bottom:10px;
}
.lasso-v2 .card:not(.is-current) .step-now{ display:none; }

/* surfaces */
.lasso-v2 section,
.lasso-v2 .card{
  background:#fff; border:1px solid var(--line); border-radius:18px;
  padding:28px 30px; margin-top:24px; box-shadow:var(--card-shadow);
}
.lasso-v2 section:first-child,
.lasso-v2 .card:first-child{ margin-top:0; }
/* Equal-height card idiom (`card h-100` + `mt-auto` on the footer). Bootstrap
   makes every card a flex column with `card-body` set to grow; this theme
   restyled the card as a plain padded surface and dropped that, so the body
   sized to its content, `mt-auto` had no spare room, and a row of cards ended
   up with their buttons at whatever height the copy happened to finish —
   visible on /labs. Scoped to `.h-100`, which is the class those cards already
   use to say they want to fill their column, so the other card usages keep
   plain block flow. */
.lasso-v2 .card.h-100{ display:flex; flex-direction:column; }
.lasso-v2 .card.h-100 > .card-body{ flex:1 1 auto; display:flex; flex-direction:column; }

/* headings */
.lasso-v2 h1{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:32px; color:var(--ink); line-height:1.15; margin:0 0 6px; }
.lasso-v2 h2{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:24px; color:var(--ink); margin:0 0 4px; }
.lasso-v2 h3{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:18px; color:var(--ink); margin:0 0 4px; }
/* h4–h6 never got the v2 treatment, so they kept the browser's own
   `margin: 1.33em 0` … `2.33em 0`. Bootstrap's reboot would have zeroed those,
   but the clean layout does not load it. On the Trust Signals step that put a
   ~43px margin above the panel headings inside their flex header row, which is
   what left the heading and its copy floating at the bottom of the box.
   Margins only — sizes are deliberately left alone so this does not reflow type
   across every v2 page. */
.lasso-v2 h4, .lasso-v2 h5, .lasso-v2 h6{ margin:0 0 4px; }
.lasso-v2 section > h2{ font-size:20px; }
.lasso-v2 h3.sub{
  font-family:'Inter',sans-serif; font-size:12px; font-weight:700;
  letter-spacing:.08em; text-transform:uppercase; color:var(--muted);
  margin:24px 0 12px;
}
.lasso-v2 h3.sub:first-of-type{ margin-top:0; }
.lasso-v2 .lead{ font-size:16px; color:var(--muted); line-height:1.6; margin-bottom:8px; max-width:720px; }
.lasso-v2 .muted{ color:var(--muted); }
.lasso-v2 .desc{ font-size:14px; color:var(--muted); margin-bottom:22px; line-height:1.5; }

/* buttons */
/* `border:1.5px solid transparent`, not `border:0`: the ghost variants below
   (btn-secondary / btn-info / btn-outline-*) carry a real 1.5px border, so with
   a zero-border base every solid button sat 3px shorter and narrower than the
   outline button beside it. The invoice view page shows it plainly — "Back to
   Index" (outline) against "PDF" and "Re-send Invoice" (solid) in one row.
   A transparent border on the base gives every button the same box, which is
   how Bootstrap itself avoids this. */
.lasso-v2 .btn{
  border:1.5px solid transparent; cursor:pointer; font-family:inherit; font-weight:700;
  border-radius:10px; font-size:14px; padding:11px 20px;
  display:inline-flex; align-items:center; gap:8px; text-decoration:none;
  line-height:1.2;
}
/* A cell that stands in for a button but is a state, not an action — "Inactive" where
   another row has an LP link. It must not read as a button: no border, no fill, no
   hover, no pointer. It still borrows .btn's metrics above, because a bare text node
   has none of a button's height and the row it sits in would stop lining up with the
   rows around it. */
.lasso-v2 .lp-slot-text{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:5.25rem; padding:11px 20px; border:1.5px solid transparent;
  font-size:14px; line-height:1.2; color:var(--muted);
}

/* NOTE: app.css forces .btn-primary/.btn-success color with !important, so the
   themed variants below must also use !important to win (same-!important → higher
   specificity of `.lasso-v2 .btn-*` decides). */
.lasso-v2 .btn-primary{ background:var(--brand-red)!important; border-color:var(--brand-red)!important; color:#fff!important; box-shadow:0 8px 18px rgba(232,54,43,.26); }
.lasso-v2 .btn-primary:hover{ background:var(--brand-red-dark)!important; border-color:var(--brand-red-dark)!important; color:#fff!important; }
.lasso-v2 .btn-dark{ background:var(--ink)!important; border-color:var(--ink)!important; color:#fff!important; }
.lasso-v2 .btn-dark:hover{ background:#000!important; border-color:#000!important; color:#fff!important; }
.lasso-v2 .btn-ghost{ background:#fff!important; color:var(--text)!important; border:1.5px solid var(--line)!important; }
.lasso-v2 .btn-ghost:hover{ border-color:#CBD1D8!important; color:var(--text)!important; }
.lasso-v2 .btn-teal{ background:#fff!important; color:var(--teal-dark)!important; border:1.5px solid #BEE5EC!important; }
.lasso-v2 .btn-teal:hover{ background:#F0FAFB!important; color:var(--teal-dark)!important; }
/* Solid blue fill for secondary navigation away from a form ("Back to Index"),
   which the ghost treatment below leaves indistinguishable from the page. Uses
   the palette's --blue rather than a lighter tint: white on #2F6FD6 is 4.8:1
   and clears WCAG AA, while the pale blues (#E7F0FE, the badge-info fill) are
   nowhere near readable under white text. */
.lasso-v2 .btn-blue{ background:var(--blue)!important; border-color:var(--blue)!important; color:#fff!important; box-shadow:0 8px 18px rgba(47,111,214,.24); }
.lasso-v2 .btn-blue:hover{ background:#2559B0!important; border-color:#2559B0!important; color:#fff!important; }
.lasso-v2 .btn-danger, .lasso-v2 .btn-outline-danger{ background:#fff!important; color:var(--brand-red)!important; border:1.5px solid #F3C9C4!important; }
.lasso-v2 .btn-danger:hover, .lasso-v2 .btn-outline-danger:hover{ background:#FDECEA!important; color:var(--brand-red)!important; }
/* .btn-warning had NO v2 rule, so legacy admin pages (Cron Jobs "Clear Cache", the
   per-row "repeat" action) rendered it as an unstyled link with no button chrome.
   Quiet-amber outline, matching the .btn-danger/.btn-teal treatment rather than a
   solid amber fill — white-on-#E8912B is ~2.5:1 contrast and fails WCAG AA, while
   #B4690E on #FFF3E0 is the pairing the design system already uses for amber. */
.lasso-v2 .btn-warning{ background:#FFF3E0!important; color:#B4690E!important; border:1.5px solid #F3D9B5!important; }
.lasso-v2 .btn-warning:hover{ background:#FDEBD2!important; color:#8F520A!important; }
/* keep semantic green for .btn-success (app.css forces an olive green !important) */
.lasso-v2 .btn-success, .lasso-v2 .btn-outline-success{ background:var(--green)!important; border-color:var(--green)!important; color:#fff!important; box-shadow:none; }
.lasso-v2 .btn-success:hover, .lasso-v2 .btn-outline-success:hover{ background:#188047!important; border-color:#188047!important; color:#fff!important; }
/* neutral/secondary/info buttons (Reset, etc.) -> ghost look */
.lasso-v2 .btn-secondary, .lasso-v2 .btn-info, .lasso-v2 .btn-outline-secondary,
.lasso-v2 .btn-outline-primary{ background:#fff!important; color:var(--text)!important; border:1.5px solid var(--line)!important; box-shadow:none!important; }
.lasso-v2 .btn-secondary:hover, .lasso-v2 .btn-info:hover{ border-color:#CBD1D8!important; color:var(--ink)!important; }

/* --- shared toolbar / pagination / sort links inside converted (.lasso-v2) pages --- */
/* real inputs/selects only — NOT button.form-control (search.php's Search button carries .form-control.btn) */
.lasso-v2 input.form-control, .lasso-v2 select.form-control, .lasso-v2 textarea.form-control,
.lasso-v2 .custom-select, .lasso-v2 input[type="text"], .lasso-v2 input[type="search"], .lasso-v2 input[type="email"]{
  border:1.5px solid var(--line)!important; border-radius:10px!important;
  font-family:inherit; font-size:14px; color:var(--text); background-color:#fff!important; box-shadow:none!important;
}
.lasso-v2 input.form-control:focus, .lasso-v2 select.form-control:focus, .lasso-v2 .custom-select:focus{
  border-color:var(--teal)!important; box-shadow:0 0 0 4px rgba(23,162,184,.14)!important;
}
/* Give plain form inputs a consistent ~40px height. Defined BEFORE .inp/.service
   rules so icon inputs, service rows and the search toolbar keep their own more
   specific padding; only otherwise-unpadded inputs (geo targets, trust-signals,
   etc.) pick this up. */
.lasso-v2 input.form-control, .lasso-v2 textarea.form-control, .lasso-v2 select.form-control,
.lasso-v2 input[type="text"], .lasso-v2 input[type="email"], .lasso-v2 input[type="number"]{ padding:9px 12px; }

/* ── Bootstrap 4 input-group (field + prepend/append addons) ──────────────────
   21 admin templates wrap a field in `.input-group` with `.input-group-text`
   addons — the category Headlines/Descriptions index + remaining-character
   counters, the date-range pickers, the invoice and teams forms. Bootstrap is
   not loaded under lasso_v2, so `.input-group` had no `display:flex` and the
   addons fell out as block boxes: the "1)" index sat on its own line above the
   field and the character count on its own line below it.
   The joined-edge radii carry !important because the .form-control shim above
   sets `border-radius:10px!important` on every input. */
.lasso-v2 .input-group{ position:relative; display:flex; flex-wrap:wrap; align-items:stretch; width:100%; }
.lasso-v2 .input-group > .form-control{ position:relative; flex:1 1 auto; width:1%; min-width:0; }
.lasso-v2 .input-group-prepend, .lasso-v2 .input-group-append{ display:flex; }
.lasso-v2 .input-group-text{
  display:flex; align-items:center; white-space:nowrap;
  padding:9px 12px; font-size:14px; color:var(--muted);
  background:#F1F3F5; border:1.5px solid var(--line); border-radius:10px;
}
/* square off the two edges where an addon butts against the field */
.lasso-v2 .input-group-prepend .input-group-text{ border-right:0; border-top-right-radius:0; border-bottom-right-radius:0; }
.lasso-v2 .input-group-append .input-group-text{ border-left:0; border-top-left-radius:0; border-bottom-left-radius:0; }
.lasso-v2 .input-group > .form-control:not(:first-child){ border-top-left-radius:0!important; border-bottom-left-radius:0!important; }
.lasso-v2 .input-group > .form-control:not(:last-child){ border-top-right-radius:0!important; border-bottom-right-radius:0!important; }
.lasso-v2 thead th a{ color:var(--muted)!important; text-decoration:none; }
.lasso-v2 thead th a:hover{ color:var(--ink)!important; }
/* …except in a title bar. The rule above is for the column-header sort links,
   which sit on the pale thead fill and should be muted. A report table's TITLE
   row is also a `thead th`, but it carries a saturated fill — and several of them
   hold a link (the big board's "Source Performance Summary | July-2026" and
   "Call Lead Summary | July-2026"). Those came out mid-grey on near-black, which
   the `!important` above forced through both the `.text-white` on the link and
   the td/th contrast safety net further down this file. Same !important, higher
   specificity. Underlined, since white-on-fill removes the colour cue. */
.lasso-v2 thead th.lassobigBoardHeading a,
.lasso-v2 thead th.bg-dark a,
.lasso-v2 thead th.bg-primary a,
.lasso-v2 thead th.bg-success a,
.lasso-v2 thead th.bg-danger a,
.lasso-v2 thead th.bg-info a,
.lasso-v2 thead th.bg-secondary a,
.lasso-v2 thead th.clsBlueBkgrnd a,
.lasso-v2 thead th.lassobigBoardHeading a:hover,
.lasso-v2 thead th.bg-dark a:hover,
.lasso-v2 thead th.bg-primary a:hover,
.lasso-v2 thead th.bg-success a:hover,
.lasso-v2 thead th.bg-danger a:hover,
.lasso-v2 thead th.bg-info a:hover,
.lasso-v2 thead th.bg-secondary a:hover,
.lasso-v2 thead th.clsBlueBkgrnd a:hover{ color:#fff!important; text-decoration:underline; }
/* Pager (element('pagination')) — record count on the left, clean prev/next +
   numbered square buttons on the right, per resources/new-designs/admin-portal-redesign.html
   (.pager / .pg / .pg.cur). Bootstrap is NOT loaded under lasso_v2, so the flex +
   list reset is set explicitly here rather than inherited from .pagination. */
.lasso-v2 .lasso-pager{ margin-top:8px; }
.lasso-v2 .lasso-pager .lp-count{ color:var(--muted); font-size:13px; margin:0; }
.lasso-v2 .lasso-pager .lp-count strong{ color:var(--ink); font-weight:700; }
.lasso-v2 .pagination{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; list-style:none; padding:0; margin:0; }
.lasso-v2 .pagination .page-item{ list-style:none; }
.lasso-v2 .pagination .page-link{
  display:flex; align-items:center; justify-content:center;
  min-width:34px; height:34px; padding:0 7px;
  border:1.5px solid var(--line); border-radius:9px;
  background:#fff; color:var(--text); font-size:13px; line-height:1;
  text-decoration:none; transition:border-color .12s, color .12s, background .12s;
}
.lasso-v2 .pagination .page-item:not(.active):not(.disabled) .page-link:hover{
  border-color:var(--ink); color:var(--ink);
}
.lasso-v2 .pagination .page-item.active .page-link{ background:var(--ink); border-color:var(--ink); color:#fff; }
.lasso-v2 .pagination .page-item.disabled .page-link{ opacity:.4; cursor:default; pointer-events:none; }
.lasso-v2 .btn[disabled],
.lasso-v2 .btn:disabled{ opacity:.5; cursor:default; box-shadow:none; }
.lasso-v2 .btn.sm{ padding:8px 14px; font-size:12.5px; border-radius:9px; }

/* form controls */
.lasso-v2 .field-label{ display:block; font-weight:600; font-size:13px; color:var(--ink); margin-bottom:7px; }
.lasso-v2 .req{ color:var(--brand-red); }
/* Inline action inside a field-level message — lets a validation message offer
   the fix (e.g. "Create it") instead of only naming the problem. */
.lasso-v2 .btn-link-inline{
  background:none; border:0; padding:0; font:inherit; font-weight:700;
  color:var(--brand-red); text-decoration:underline; cursor:pointer;
}
.lasso-v2 .btn-link-inline:hover{ color:var(--ink); }
.lasso-v2 .btn-link-inline:disabled{ opacity:.6; cursor:default; text-decoration:none; }
/* Auto required-asterisk. app.css owns this rule for the legacy layout, but the
   clean lasso_v2 layout doesn't load app.css — port it here (scoped) so the
   customer-setup wizard's required fields show the red "*" the mockup calls for. */
.lasso-v2 .dasterisk label:after,
.lasso-v2 .asterisk .input.required > label:after{ color:var(--brand-red); content:"*"; position:relative; margin-left:4px; top:1px; }
.lasso-v2 .inp{ position:relative; max-width:320px; }
.lasso-v2 .inp .lead2{
  position:absolute; left:1.5px; top:1.5px; bottom:1.5px; width:38px;
  display:flex; align-items:center; justify-content:center; color:var(--muted);
  background:#F5F7F9; border-right:1px solid var(--line); border-radius:9px 0 0 9px;
}
.lasso-v2 .inp input{
  width:100%; padding:11px 12px 11px 50px; border:1.5px solid var(--line);
  border-radius:10px; font-size:14px; font-family:inherit; color:var(--text);
}
/* Text addon instead of an icon — used for the website field's "https://", so the scheme is
   visibly part of the control and nobody types it twice. Wider than the 38px icon slot, with
   the input's padding widened to match. */
.lasso-v2 .inp .lead2.lead2-text{
  width:64px; font-size:12.5px; letter-spacing:-.2px; font-family:inherit;
}
.lasso-v2 .inp-prefixed input{ padding-left:76px; }
.lasso-v2 .inp input:focus{ outline:none; border-color:var(--teal); box-shadow:0 0 0 4px rgba(23,162,184,.14); }
.lasso-v2 .selm{ position:relative; max-width:320px; }
.lasso-v2 .selm select{
  width:100%; appearance:none; -webkit-appearance:none; border:1.5px solid var(--line);
  border-radius:10px; padding:11px 34px 11px 13px; font-size:14px; font-family:inherit;
  background:#fff; cursor:pointer; color:var(--text);
}
.lasso-v2 .selm .chev{ position:absolute; right:12px; top:50%; transform:translateY(-50%); color:var(--muted); pointer-events:none; }

/* ----------------------------------------------------------------------------
   Autocomplete dropdown + repeating "service" rows.
   portal.css owns these for the legacy layout, but the clean lasso_v2 layout
   deliberately doesn't load portal.css — so port + restyle them here (scoped,
   in the v2 palette). Shared by the wizard: primary-category (basic), services,
   trust-signals extras, and any other *-autocomplete widget.
   -------------------------------------------------------------------------- */
.lasso-v2 .autocomplete-list{
  position:absolute; top:100%; left:0; right:0; background:#fff;
  border:1.5px solid var(--line); border-top:none; border-radius:0 0 10px 10px;
  max-height:220px; overflow-y:auto; z-index:200; display:none;
  box-shadow:0 12px 26px rgba(20,25,35,.10);
}
.lasso-v2 .ac-item{ padding:9px 13px; cursor:pointer; font-size:13.5px; color:var(--text); }
.lasso-v2 .ac-item:hover,
.lasso-v2 .ac-item.ac-active{ background:var(--brand-red); color:#fff; }
/* "Create new" is the escape hatch when nothing in the list fits, so it must be
   reachable without scrolling a long result set. Pinned to the bottom edge of
   the list instead of moved to the top: keeping it last leaves the real matches
   first for both the eye and ArrowDown, while sticky keeps it always in view.
   The opaque background is load-bearing — results scroll underneath it. */
.lasso-v2 .ac-item.ac-create-new{
  position:sticky; bottom:0; z-index:1;
  background:#F8F9FA; border-top:1px solid var(--line);
  color:var(--text); font-style:normal; font-weight:600;
}
.lasso-v2 .ac-item.ac-create-new .ac-create-label{ color:var(--muted); font-weight:500; margin-right:4px; }
.lasso-v2 .ac-item.ac-create-new:hover,
.lasso-v2 .ac-item.ac-create-new.ac-active{ background:var(--ink); color:#fff; }
.lasso-v2 .ac-item.ac-create-new:hover .ac-create-label,
.lasso-v2 .ac-item.ac-create-new.ac-active .ac-create-label{ color:rgba(255,255,255,.78); }
.lasso-v2 .ac-item.ac-no-results{ color:var(--muted); cursor:default; }
/* "why did this surface" hint on a category matched through its keywords/services/ad copy
   rather than its name. Muted and secondary, but must invert on hover/active or it goes
   invisible against the red row. */
.lasso-v2 .ac-item .ac-via{
  display:block; font-size:11.5px; color:var(--muted); margin-top:2px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.lasso-v2 .ac-item:hover .ac-via,
.lasso-v2 .ac-item.ac-active .ac-via{ color:rgba(255,255,255,.82); }

.lasso-v2 .service-fields-wrapper{ display:grid; grid-template-columns:1fr 1fr; gap:12px 16px; }
.lasso-v2 .service-row{ display:flex; align-items:center; position:relative; margin-bottom:0; }
.lasso-v2 .service-row .service-input{ flex:1; padding:11px 12px; }
.lasso-v2 .service-row .autocomplete-list{ right:2.6rem; }
.lasso-v2 .service-row .btn-remove-service{
  margin-left:8px; color:var(--brand-red); background:none; border:0; font-size:19px;
  line-height:1; cursor:pointer; padding:0 6px; opacity:.6;
}
.lasso-v2 .service-row .btn-remove-service:hover{ opacity:1; }
.lasso-v2 .service-count{ grid-column:1 / -1; font-size:12.5px; color:var(--muted); margin-top:4px; }
/* Still short of the minimum — the count is the thing standing between the user
   and the next step, so it stops being incidental grey text. */
.lasso-v2 .service-count.is-short{ color:var(--brand-red); font-weight:700; }
/* The rule itself, directly under the running count. It was a muted parenthetical
   beside the field label and went unread; the step then refused to save without
   ever having stated the requirement plainly. */
.lasso-v2 .services-rule{
  grid-column:1 / -1; margin:6px 0 0; font-size:15px; font-weight:800; color:var(--ink);
}
/* How to actually add one. The mechanism - type, pick a match or create - was
   never described anywhere on the page. */
.lasso-v2 .services-howto{
  font-size:13px; color:var(--muted); line-height:1.55; margin:2px 0 12px; max-width:70ch;
}
.lasso-v2 .services-howto strong{ color:var(--ink); font-weight:700; }
@media(max-width:720px){ .lasso-v2 .service-fields-wrapper{ grid-template-columns:1fr; } }

/* ---- Payment Options step: selectable payment-method cards -------------- */
.lasso-v2 .customer-step-layout fieldset{ border:0; padding:0; margin:0; min-width:0; }
.lasso-v2 .payment-options-grid{ display:grid; gap:14px; grid-template-columns:repeat(var(--pay-cols,4),minmax(0,1fr)); margin-top:14px; }
@media(max-width:600px){ .lasso-v2 .payment-options-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
.lasso-v2 .payment-card{ display:block; position:relative; cursor:pointer; }
.lasso-v2 .card-input-hidden{ position:absolute; opacity:0; width:0; height:0; }
.lasso-v2 .payment-card .card-content{
  background:#fff; border:1.5px solid var(--line); border-radius:12px; padding:16px 12px; height:100%;
  text-align:center; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:6px; transition:border-color .15s, box-shadow .15s, transform .15s;
}
.lasso-v2 .payment-card .icon{ color:var(--muted); }
.lasso-v2 .payment-card .name{ font-weight:600; font-size:13px; color:var(--ink); }
.lasso-v2 .payment-card:hover .card-content{ transform:translateY(-2px); box-shadow:var(--card-shadow); border-color:#CBD1D8; }
.lasso-v2 .card-input-hidden:checked + .card-content{ border-color:var(--brand-red); box-shadow:0 0 0 3px rgba(232,54,43,.16); background:#FEF6F5; }
.lasso-v2 .card-input-hidden:checked + .card-content::after{
  content:"\f00c"; font-family:"Font Awesome 6 Free"; font-weight:900; position:absolute;
  top:8px; right:10px; color:var(--brand-red); font-size:12px;
}

/* ---- Recommendations step: 3-up selectable plan cards ------------------- */
.lasso-v2 .recommendation-radio{ position:absolute; opacity:0; pointer-events:none; width:0; height:0; margin:0; }
.lasso-v2 .recommendation-card{
  position:relative; display:block; cursor:pointer; background:#fff; height:100%;
  border:1.5px solid var(--line); border-radius:14px; padding:18px;
  transition:border-color .15s, box-shadow .15s;
}
.lasso-v2 .recommendation-card-recommended{ border-color:var(--green)!important; box-shadow:0 0 0 3px rgba(31,157,87,.18); }
.lasso-v2 .recommendation-card:hover,
.lasso-v2 .recommendation-card-selected{ border-color:var(--brand-red)!important; box-shadow:0 0 0 3px rgba(232,54,43,.16); }
.lasso-v2 .recommendation-card-disabled{ opacity:.7; }
.lasso-v2 .recommendation-card-disabled label{ cursor:not-allowed; }
/* Why a lower tier is unavailable, at the foot of the card. It used to be a long
   paragraph stacked above the tier name, which pushed the plan and price halfway
   down and made the one card the customer cannot choose the tallest and busiest
   of the three. */
.lasso-v2 .recommendation-downgrade-note{
  display:block; margin-top:12px; padding-top:11px; border-top:1px solid var(--line);
  font-size:12px; line-height:1.5; color:var(--muted);
}
.lasso-v2 .recommendation-downgrade-note a{
  color:var(--teal-dark); font-weight:600; text-decoration:underline; pointer-events:auto; cursor:pointer;
}
/* Name/price proportions follow the redesign: the price is the thing being
   compared across the three cards, so it leads and the tier name sits above it. */
.lasso-v2 .recommendation-tier-name{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:15px; color:var(--ink); }
.lasso-v2 .recommendation-budget{ display:block; white-space:nowrap; font-weight:800; font-size:24px; letter-spacing:-.02em; color:var(--ink); }
.lasso-v2 .recommendation-budget-period{ font-size:13px; font-weight:600; color:var(--muted); letter-spacing:0; }
/* Tier blurb — comes from plans.description, the copy the business already
   writes for each tier. */
.lasso-v2 .recommendation-tier-desc{
  font-size:12.5px; line-height:1.45; color:var(--muted); margin:8px 0 0;
}
/* The real radio is visually hidden, so the card draws its own dot. The extra
   right padding keeps the tier name clear of it — the three-class selector is
   needed to beat lasso-v2-layout.css's `.p-3` utility, which the card carries
   and which resets padding on all four sides. */
.lasso-v2 .recommendation-cards-row .recommendation-card{ padding-right:46px; }
.lasso-v2 .recommendation-radio-dot{
  position:absolute; top:16px; right:16px; width:20px; height:20px; border-radius:50%;
  border:2px solid var(--line); background:#fff; transition:border-color .15s, background .15s;
}
.lasso-v2 .recommendation-card-selected .recommendation-radio-dot{
  border-color:var(--brand-red);
  background:radial-gradient(circle at center, var(--brand-red) 0 5px, #fff 6px 20px);
}

/* Actions bar: running readout of the current selection beside the buttons.
   nowrap — with wrapping on, the readout dropped onto its own line above the
   buttons as soon as the column got below ~1280px. It shrinks and ellipses
   instead, and below 1200px it goes away entirely: that is the width where the
   plan cards stack one per row, so the selected card is unmistakable on its own
   and the readout is not carrying any information. */
/* The step's own heading. It was rendering at h5 scale, smaller than the plan
   names in the cards below it, so the thing naming the whole decision was the
   least prominent text on the page. */
.lasso-v2 .recommendation-page-title{
  font-size:22px; font-weight:800; color:var(--ink); line-height:1.2; letter-spacing:-.01em;
}
.lasso-v2 .recommendation-actions{
  display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:nowrap;
  margin-top:26px;
}
/* The shared .form-actions element carries its own 26px top margin to space it
   from the form above. Inside this bar that margin only pushed the buttons 26px
   below the readout's centre line, so it moves to the bar. */
.lasso-v2 .recommendation-actions .form-actions{ flex:1 1 auto; min-width:0; margin-top:0; }
.lasso-v2 .recommendation-selected-readout{
  font-size:12.5px; color:var(--muted); flex:0 1 auto; min-width:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.lasso-v2 .recommendation-selected-readout b{ color:var(--text); font-weight:700; }
@media(max-width:1199px){
  .lasso-v2 .recommendation-selected-readout{ display:none; }
}
/* SAVE sits hard left on every other wizard step. Here the readout was first in
   the bar and pushed SAVE inward, so this one step put its buttons somewhere
   else. display:contents lifts the two buttons out of .form-actions and into the
   bar's own flex row, letting the readout take the middle without duplicating
   any button or touching the shared element the other nine steps render.
   Scoped above 1199px: below that the readout is hidden, and below 768px
   .form-actions becomes the fixed bottom bar and must keep its box. */
@media(min-width:1200px){
  /* !important because the shared element carries Bootstrap's .d-flex utility,
     which is itself display:flex !important — without matching it the buttons
     stay inside their own flex box and the order below has no effect. */
  .lasso-v2 .recommendation-actions .form-actions{ display:contents !important; }
  .lasso-v2 .recommendation-actions .customer-step-btn-return{ order:1; }
  .lasso-v2 .recommendation-actions .recommendation-selected-readout{
    order:2; flex:1 1 auto; text-align:center;
  }
  .lasso-v2 .recommendation-actions .customer-step-btn-continue{ order:3; }
}
/* Phone: the actions bar pins to the bottom, per the redesign's mobile frame —
   with three stacked plan cards the buttons were otherwise below the fold the
   whole time you were choosing. The real .form-actions buttons are made sticky
   rather than mirrored into a second bar, so there is still exactly one SAVE
   and one SAVE & CONTINUE in the form. */
@media(max-width:767.98px){
  /* the readout is hidden at this width, so the wrapper is just a pass-through */
  .lasso-v2 .recommendation-actions{ display:block; margin-top:0; }
}

/* ---- Wizard: pinned action bar on mobile -------------------------------
   `.m-footbar` in the wizard mockups (wizard-basic-info-redesign.html,
   wizard-images-redesign.html): on a phone, Save / Save & continue pin to the
   bottom of the screen rather than sitting at the end of a form that can run
   two or three screens long. Applied to every step that renders
   ele_customer_steps_form_actions, which is all ten of them.

   The real buttons are repositioned rather than mirrored into a second bar, so
   each form still holds exactly one SAVE and one SAVE & CONTINUE — a duplicate
   pair would mean two `save_return` submits. Fixed rather than sticky because
   the bar is the last thing inside its card and a sticky element would have no
   container left to stick within. */
@media(max-width:767.98px){
  .lasso-v2 .customer-step-layout .form-actions{
    position:fixed; left:0; right:0; bottom:0; z-index:1030;
    background:#fff; border-top:1px solid var(--line);
    margin:0; padding:12px 16px; gap:10px; flex-wrap:nowrap;
    box-shadow:0 -6px 18px rgba(20,25,35,.08);
  }
  .lasso-v2 .customer-step-layout .form-actions > .btn{ flex:1 1 0; justify-content:center; }
  /* the wrapper's divider would otherwise be left hanging with nothing under it */
  .lasso-v2 .customer-step-layout .step-form-actions-wrap{
    margin-top:0 !important; padding-top:0 !important; border-top:0 !important;
  }
  /* keep the end of the page clear of the pinned bar */
  .lasso-v2 .customer-step-layout{ padding-bottom:24px; }
  /* …and clear it at the page level too. footer.php renders after <main>, as a
     sibling inside .lv2-shell, so padding on .customer-step-layout stopped
     short of the footer and the bar covered the footer band once you scrolled
     to the end. :has() keys on the bar itself, not on the step layout, so a
     page that renders no action bar keeps its normal footer with no dead
     space under it. */
  body.lasso-v2:has(.customer-step-layout .form-actions) .lv2-shell{ padding-bottom:84px; }
}

/* "Good to know" — icon tiles instead of emoji bullets.
   Boxed as a white card to match ele_fact, which every other wizard step uses in
   this rail. Unboxed 13px text beside a boxed form read as a footnote, so the
   reassurance nobody doubts (no hidden fees, secure checkout) went unread at the
   one step where the customer is deciding what to spend. */
.lasso-v2 .recommendation-sidebar{
  background:#fff; border:1px solid var(--line); border-radius:16px;
  padding:18px 18px 16px; margin-bottom:16px; box-shadow:0 4px 16px rgba(20,24,31,.06);
}
.lasso-v2 .recommendation-sidebar .gtk-cap{
  font-size:12.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase;
  color:var(--muted); margin-bottom:15px;
}
.lasso-v2 .gtk-list{ list-style:none; margin:0; padding:0; display:grid; gap:15px; }
.lasso-v2 .gtk-list li{ display:flex; gap:12px; font-size:14px; line-height:1.5; color:var(--text); }
.lasso-v2 .gtk-ic{
  flex:none; width:28px; height:28px; border-radius:9px; background:#E6F6EC;
  display:grid; place-items:center; color:var(--green); font-size:12.5px;
}
.lasso-v2 .gtk-list b{ font-weight:700; color:var(--ink); }
/* "Recommended" ribbon. It used to sit inside the card at top:10px, where it
   ran straight through the tier name — the card is only ~180px wide, so a
   110px badge and "Getting Started" cannot share that line. Riding the top
   border instead keeps it clear of the content at every width, and leaves the
   tier names aligned across all three cards.
   Deliberately solid green rather than the tinted `.badge-success` the element
   also carries: this is a ribbon, not a status pill. Selector includes `.badge`
   so it outranks the badge variants further down the file, which would
   otherwise win on load order and wash it out to the pale tint. */
.lasso-v2 .badge.recommendation-badge-recommended,
.lasso-v2 .recommendation-badge-recommended{
  position:absolute; top:-11px; left:18px; right:auto; z-index:2; margin:0;
  background:var(--green); color:#fff; border:0;
  font-size:10.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase;
  padding:4px 11px; border-radius:999px; white-space:nowrap;
  box-shadow:0 2px 6px rgba(31,157,87,.30);
}
/* room for the ribbon to overhang the top of the recommended card */
.lasso-v2 .recommendation-cards-row{ padding-top:11px; }
/* The three cards are `flex:1 1 260px` inside the wizard's middle column, which
   is only ~45% of the viewport — so they were being squeezed well below their
   own content width and the tier name and price spilled outside the border.
   min-width:0 stops a flex item refusing to shrink, and below 1200px there is
   simply not enough room for three across, so they stack. */
.lasso-v2 .recommendation-cards-row > [class*="col-"]{ min-width:0; }
.lasso-v2 .recommendation-card{ min-width:0; overflow-wrap:break-word; }
/* The long selector is deliberate: lasso-v2-layout.css pins these columns to
   33.333% via `.customer-step-layout .card .row > .col-md-4`, so anything
   shorter loses. Below 768px that same shim already stacks them. */
@media(min-width:768px) and (max-width:1199px){
  .lasso-v2 .customer-step-layout .card .row.recommendation-cards-row > [class*="col-"]{
    flex:0 0 100%; max-width:100%;
  }
}
/* Stacked cards need real space between them. The same layout shim also sets
   `margin-bottom:4px` on every column and outspecifies `.mb-3`, so the cards
   sat flush against each other on a phone. 20px, not 12 — the Recommended
   ribbon overhangs the card top by 11px and would otherwise touch the card
   above it. */
.lasso-v2 .customer-step-layout .card .row.recommendation-cards-row > [class*="col-"]{
  margin-bottom:20px;
}
/* "Current plan" / "Scheduled" ride the top border, exactly like the Recommended
   ribbon above — and for the same reason its comment gives: a badge in normal flow
   pushes that ONE card's tier name and price down, so the three cards no longer
   start on the same line. Reported 2026-08-17 on the upgrade view, where the
   current-plan card sat visibly lower than the other two.
   At most one of these three badges can appear on a card — Recommended requires
   !isUpgradeView, Current requires isUpgradeView, and the pending target is never
   the current plan — so they can share the same position without colliding. */
.lasso-v2 .badge.recommendation-badge-current,
.lasso-v2 .recommendation-badge-current{
  position:absolute; top:-11px; left:18px; right:auto; z-index:2; margin:0;
  background:var(--muted); color:#fff; border:0;
  font-size:10.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase;
  padding:4px 11px; border-radius:999px; white-space:nowrap;
  box-shadow:0 2px 6px rgba(20,25,35,.20);
}
.lasso-v2 .badge.recommendation-badge-scheduled,
.lasso-v2 .recommendation-badge-scheduled{
  background:var(--teal-dark); box-shadow:0 2px 6px rgba(18,130,148,.30);
}
/* "Why we recommend" rationale — comfortable line-height + spacing, page font */
.lasso-v2 .recommendation-why{ font-family:inherit; line-height:1.6; }
.lasso-v2 .recommendation-why h6{ font-size:14px; }
.lasso-v2 .recommendation-why p{ margin-bottom:.7rem; }
.lasso-v2 .recommendation-why ul{ margin:0 0 .7rem; padding-left:1.2rem; }
.lasso-v2 .recommendation-why li{ margin-bottom:.55rem; }
.lasso-v2 .recommendation-why li:last-child{ margin-bottom:0; }

/* "Your selections" chips — reflect the customer's own choices back to them.
   Desktop: fixed inline label + wrapping chip row. Mobile: label stacks above
   full-width chips (see the max-width:576px block below). */
.lasso-v2 .recommendation-selections{ margin:0 0 16px; }
.lasso-v2 .recommendation-selections .rs-cap{
  font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted); margin:0 0 10px; display:flex; align-items:center; gap:6px;
}
.lasso-v2 .rs-group{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:8px; align-items:baseline; }
.lasso-v2 .rs-group:last-child{ margin-bottom:0; }
.lasso-v2 .rs-group .rs-label{ flex:0 0 84px; font-size:11.5px; font-weight:600; color:var(--muted); }
.lasso-v2 .rs-group .rs-chips{ display:flex; flex-wrap:wrap; gap:6px; flex:1; }
.lasso-v2 .rs-chip{
  display:inline-flex; align-items:center; gap:5px; white-space:nowrap;
  background:#F1F4F7; border:1px solid var(--line); border-radius:999px;
  padding:4px 11px; font-size:12.5px; font-weight:600; color:var(--ink);
}
.lasso-v2 .rs-chip i{ font-size:11px; opacity:.85; }
.lasso-v2 .rs-chip.rs-chip-industry{ background:#EAF4FB; border-color:#CFE6F5; color:#0c3a54; }
.lasso-v2 .rs-chip.rs-chip-more{ background:transparent; border-style:dashed; color:var(--muted); font-weight:600; }
/* inline hint after chips (e.g. "moderate cost per call") — self-explaining, no bullets */
.lasso-v2 .rs-group .rs-hint{ align-self:center; font-size:11.5px; font-style:italic; color:var(--muted); }
.lasso-v2 .rs-group .rs-hint::before{ content:"· "; }

/* Compact recommendation line + collapsed "Why this plan?" (keeps cards above the fold) */
.lasso-v2 .recommendation-why-compact{ line-height:1.5; }
.lasso-v2 .recommendation-why-compact .rs-rec{ font-size:13.5px; }
.lasso-v2 .recommendation-why-more{ margin-top:8px; }
.lasso-v2 .recommendation-why-more summary{ cursor:pointer; font-size:12px; font-weight:700; color:#0c5460; list-style:none; display:inline-flex; align-items:center; gap:5px; }
.lasso-v2 .recommendation-why-more summary::-webkit-details-marker{ display:none; }
.lasso-v2 .recommendation-why-more summary::before{ content:"\f105"; font-family:"Font Awesome 6 Free"; font-weight:900; font-size:11px; transition:transform .15s; }
.lasso-v2 .recommendation-why-more[open] summary::before{ transform:rotate(90deg); }
.lasso-v2 .recommendation-why-more ul{ font-size:12.5px; line-height:1.5; }
.lasso-v2 .recommendation-why-more li{ margin-bottom:.4rem; }
.lasso-v2 .recommendation-why-more li:last-child{ margin-bottom:0; }

/* Mobile: compact/subtle heading + stacked selection chips */
@media (max-width:576px){
  .lasso-v2 .recommendation-page-title{ font-size:.85rem; font-weight:600; color:var(--muted); letter-spacing:.01em; margin-bottom:.25rem; }
  .lasso-v2 .recommendation-intro{ font-size:.78rem; line-height:1.4; margin-bottom:.8rem; }
  .lasso-v2 .recommendation-selections{ background:#fff; border:1px solid var(--line); border-radius:11px; padding:12px 13px; }
  .lasso-v2 .rs-group{ display:block; margin-bottom:11px; }
  .lasso-v2 .rs-group:last-child{ margin-bottom:0; }
  .lasso-v2 .rs-group .rs-label{ display:block; flex:none; margin-bottom:6px; font-size:10px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }
  .lasso-v2 .rs-group .rs-label .rs-cnt{ color:var(--brand-red); }
  .lasso-v2 .rs-chip{ font-size:12px; padding:5px 10px; }
}

/* ---- Images step: drag/drop upload areas + stock thumbnail galleries ---- */
.lasso-v2 .upload-area{ border:2px dashed #C7CCD2; padding:20px; text-align:center; cursor:pointer; border-radius:12px; background:#F7F8FA; margin-bottom:10px; }
.lasso-v2 .upload-area:hover{ border-color:var(--teal); background:#F1FAFB; }
.lasso-v2 .upload-text{ color:var(--muted); font-size:14px; }
.lasso-v2 .upload-text i{ font-size:20px; color:var(--teal-dark); }
.lasso-v2 .select-btn{ color:var(--teal-dark); font-weight:700; text-decoration:underline; cursor:pointer; }
.lasso-v2 .preview-area{ display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; }
.lasso-v2 .preview-area img{ width:80px; height:80px; object-fit:cover; border-radius:8px; border:1px solid var(--line); padding:2px; }
.lasso-v2 .image-thumb{ position:relative; }
.lasso-v2 .remove-photo{ position:absolute; top:2px; right:2px; background:rgba(20,25,35,.62); color:#fff; border-radius:50%; width:20px; height:20px; line-height:18px; text-align:center; cursor:pointer; font-size:13px; }
.lasso-v2 .gallery-grid{ display:flex; flex-wrap:wrap; gap:8px; max-height:280px; overflow-y:auto; padding:8px; border:1px solid var(--line); border-radius:12px; }
.lasso-v2 .gallery-item{ position:relative; width:80px; height:80px; cursor:pointer; border:2px solid transparent; border-radius:8px; overflow:hidden; }
.lasso-v2 .gallery-item img{ width:100%; height:100%; object-fit:cover; display:block; }
.lasso-v2 .gallery-item .check-overlay{ display:none; position:absolute; top:3px; right:3px; width:20px; height:20px; line-height:20px; text-align:center; background:var(--brand-red); color:#fff; border-radius:50%; font-size:11px; }
.lasso-v2 .gallery-item.active{ border-color:var(--brand-red); }
.lasso-v2 .gallery-item.active .check-overlay{ display:block; }
.lasso-v2 .upload-wins-notice{ color:#856404; background:#FFF3CD; border:1px solid #FFEEBA; padding:5px 9px; border-radius:8px; font-size:12px; margin-top:6px; display:none; }

/* ---- Campaign Goals step: drag-to-select goal cards + guardrails -------- */
.lasso-v2 .goal-panel-title{ font-size:15px; font-weight:700; color:var(--ink); }
.lasso-v2 .goal-sortable{ min-height:80px; padding:10px; border:2px dashed var(--line); border-radius:12px; background:#FAFBFC; }
.lasso-v2 .goal-drag-item{
  cursor:grab; user-select:none; background:#fff; border:1.5px solid var(--line); border-radius:12px;
  padding:12px 14px; margin-bottom:8px; transition:border-color .15s, box-shadow .15s, background .15s;
}
.lasso-v2 .goal-drag-item:hover{ background:#FCFCFD; border-color:#CBD1D8; }
.lasso-v2 .goal-drag-item-selected{ border-color:var(--brand-red)!important; box-shadow:0 0 0 3px rgba(232,54,43,.14); }
.lasso-v2 .goal-drag-handle{ cursor:grab; font-size:15px; color:var(--muted); opacity:.6; }
.lasso-v2 .goal-drag-item:hover .goal-drag-handle{ opacity:1; }
.lasso-v2 .goal-priority-badge{
  display:inline-flex; align-items:center; justify-content:center; width:1.8rem; height:1.8rem; border-radius:50%;
  background:var(--brand-red); color:#fff; font-weight:700; font-size:13px; flex-shrink:0;
}
.lasso-v2 .campaign-goal-text{ font-size:14px; line-height:1.4; color:var(--text); }
.lasso-v2 .goal-placeholder{ border:2px dashed var(--brand-red); border-radius:10px; background:#FEF6F5; min-height:52px; margin-bottom:8px; list-style:none; }
.lasso-v2 .goal-locked-item{ background:#F7F8FA; border:1.5px solid var(--line); border-radius:12px; padding:8px 12px; }
.lasso-v2 .goal-locked-item .goal-priority-badge{ background:var(--muted); }
.lasso-v2 .goal-drag-item.ui-sortable-helper{ box-shadow:0 8px 20px rgba(20,25,35,.16); }
.lasso-v2 .goal-guardrails-panel-heading{ font-size:15px; font-weight:700; color:var(--ink); }
.lasso-v2 .goal-guardrails-panel .goal-guardrails-title{ list-style:none; color:var(--teal-dark); font-size:13px; font-weight:700; margin:.65rem 0 .25rem; }
.lasso-v2 .goal-guardrails-panel .goal-guardrails-item{ padding-left:1.1rem; font-size:12.5px; line-height:1.35; margin-bottom:.25rem; color:var(--muted); }

/* ---- Review step: Bootstrap-style tabs on the clean layout -------------- */
.lasso-v2 .nav-tabs{ display:flex; flex-wrap:wrap; gap:2px; list-style:none; padding:0; margin:0; border-bottom:1px solid var(--line); }
.lasso-v2 .nav-tabs .nav-item{ margin-bottom:-1px; }
.lasso-v2 .nav-tabs .nav-link{
  display:block; padding:10px 14px; font-size:13.5px; font-weight:600; color:var(--muted);
  text-decoration:none; background:none; border:0; border-bottom:2px solid transparent; cursor:pointer;
}
.lasso-v2 .nav-tabs .nav-link:hover{ color:var(--ink); }
.lasso-v2 .nav-tabs .nav-link.active{ color:var(--brand-red); border-bottom-color:var(--brand-red); }
/* ---- Bootstrap nav-pills (Categories side menu, validation pages) --------
   `.nav` never got a list reset and `.nav-pills` was never defined, so the
   Categories edit sidebar rendered as a bulleted list of plain teal links
   inside a bare grey box instead of a pill menu. The pill treatment follows
   the tabs above: muted until active, brand red when active. */
.lasso-v2 .nav{ display:flex; flex-wrap:wrap; list-style:none; margin:0; padding:0; }
.lasso-v2 .nav > li{ list-style:none; }
.lasso-v2 .nav-pills{ gap:2px; }
.lasso-v2 .nav-pills .nav-link{
  display:block; padding:7px 12px; border-radius:8px; font-size:13.5px;
  font-weight:600; color:var(--text); text-decoration:none; background:none; border:0;
}
.lasso-v2 .nav-pills .nav-link:hover{ background:#EEF1F4; color:var(--ink); text-decoration:none; }
.lasso-v2 .nav-pills .nav-link.active{ background:var(--brand-red); color:#fff; }
/* `flex-lg-column` is what actually makes the sidebar vertical; without it the
   pills tried to sit in a row inside a two-column-wide aside.
   Deliberately qualified with `.nav` rather than shipped as bare `.flex-column`
   / `.flex-lg-column` utilities: the global mega-menu <ul> carries
   `navbar-nav flex-lg-row flex-column`, and a bare .flex-column would stand the
   whole desktop nav on end. It has no `nav` class, so this cannot reach it. */
.lasso-v2 .nav.flex-column{ flex-direction:column; }
@media (min-width:992px){ .lasso-v2 .nav.flex-lg-column{ flex-direction:column; } }
/* ...but the utility is also needed OFF the nav. 15 templates put
   `d-flex flex-column` on ordinary boxes — `.card-body d-flex flex-column` on
   the Labs cards, `d-flex flex-column h-100` on several dashboards — and with
   only the `.nav`-qualified rule above they got `display:flex` with no
   direction, so they laid out as a ROW: title, description and button
   overlapping side by side. Excluding `.navbar-nav` keeps the protection the
   rule above was written for — the mega-menu <ul> carries
   `navbar-nav flex-lg-row flex-column`, and this still cannot reach it. */
.lasso-v2 .flex-column:not(.navbar-nav){ flex-direction:column; }
@media (min-width:992px){ .lasso-v2 .flex-lg-column:not(.navbar-nav){ flex-direction:column; } }
.lasso-v2 .nav-justified{ width:100%; }
.lasso-v2 .nav-justified > .nav-item{ flex:1 1 auto; text-align:center; }
/* The separators between pill groups. Unstyled they were empty <li> bullets —
   which is where the stray bullet points between the groups came from. */
.lasso-v2 .nav > li.divider{ width:100%; list-style:none; }
.lasso-v2 .dropdown-divider{
  height:0; margin:6px 0; border-top:1px solid var(--line); overflow:hidden;
}
.lasso-v2 .border-primary{ border-color:var(--brand-red) !important; }
.lasso-v2 .font08em{ font-size:.8em; }

/* ---- Owner's floating action bar (element/footer.php) --------------------
   On every non-welcome page an owner gets the big-board buttons pinned to the
   bottom. Both classes lived only in app.css, so the bar lost its sticky
   position entirely and the buttons fell to the end of the document. */
.lasso-v2 .stickyBar{ position:sticky; bottom:0; z-index:99; width:100%; }
.lasso-v2 .clsFloatingAdminFooter{
  margin:0 auto; padding:8px 32px;
  border-top:1px solid var(--line); box-shadow:0 -4px 14px -10px rgba(20,25,35,.35);
}
/* The bar is full-bleed but the buttons inside it are a .row, which the theme
   gives align-items:center — without a max width the three stretch the whole
   viewport. Keep them on the page's own gutter. */
.lasso-v2 .clsFloatingAdminFooter .clsWelcomeButtonParentDiv{ margin:0; }

.lasso-v2 .tab-content > .tab-pane{ display:none; }
.lasso-v2 .tab-content > .tab-pane.active{ display:block; }
.lasso-v2 .fade{ transition:opacity .15s linear; }
.lasso-v2 .fade:not(.show){ opacity:0; }
/* review frames (portal.css owns these) — give the tabbed summary + checkout
   their own white cards so they don't sit bare on the page background. */
.lasso-v2 .review-tabs-frame{ background:#fff; border:1px solid var(--line); border-radius:14px; margin-top:1rem; overflow:hidden; box-shadow:var(--card-shadow); }
.lasso-v2 .review-tabs-frame > #reviewTabs{ margin:0; padding:0 .75rem; background:#F7F8FA; border-bottom:1px solid var(--line); }
.lasso-v2 .review-tabs-frame > #reviewTabContent{ padding:1.25rem; min-height:340px; }
.lasso-v2 .review-tabs-frame .tab-pane > p.text-muted.small:first-child{ margin-bottom:.85rem; padding-bottom:.5rem; border-bottom:1px dashed var(--line); }
.lasso-v2 .review-checkout-cta{ background:#fff; border:1px solid var(--line); border-radius:14px; margin-top:1rem; padding:2rem 1.25rem; box-shadow:var(--card-shadow); }

/* ---- Review & Payment re-skin ------------------------------------------
   Per resources/new-designs/completed/review-payment-redesign.html.
   The seven section tabs used to wrap onto a second row on desktop (three on
   mobile), which read as a broken control. #reviewTabs is now a single nowrap
   row that scrolls horizontally instead. Scoped to #reviewTabs, NOT to
   `.nav-tabs` — other v2 pages rely on the wrapping behaviour. */
.lasso-v2 .review-tabs-frame > #reviewTabs{
  flex-wrap:nowrap; overflow-x:auto; overscroll-behavior-x:contain;
  scrollbar-width:none; -ms-overflow-style:none;
}
/* A nowrap strip has a wide min-content width; without min-width:0 the flex
   columns refuse to shrink and the checkout card wraps under the tabs. */
.lasso-v2 .review-checkout-row > .col-lg-8,
.lasso-v2 .review-checkout-row > .col-lg-4{ min-width:0; }
.lasso-v2 .review-tabs-frame > #reviewTabs::-webkit-scrollbar{ display:none; }
/* Overflow affordance: the scrollbar is hidden, so the strip fades out on
   whichever side still has tabs off-screen. Classes are toggled by the scroll
   handler in step_review.php. */
.lasso-v2 #reviewTabs.ovf-end:not(.ovf-start){
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 44px),transparent);
          mask-image:linear-gradient(90deg,#000 calc(100% - 44px),transparent);
}
.lasso-v2 #reviewTabs.ovf-start:not(.ovf-end){
  -webkit-mask-image:linear-gradient(270deg,#000 calc(100% - 44px),transparent);
          mask-image:linear-gradient(270deg,#000 calc(100% - 44px),transparent);
}
.lasso-v2 #reviewTabs.ovf-start.ovf-end{
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 44px,#000 calc(100% - 44px),transparent);
          mask-image:linear-gradient(90deg,transparent,#000 44px,#000 calc(100% - 44px),transparent);
}
.lasso-v2 .review-tabs-frame > #reviewTabs .nav-item{ flex:none; }
.lasso-v2 .review-tabs-frame > #reviewTabs .nav-link{
  display:inline-flex; align-items:center; gap:7px; white-space:nowrap; padding:14px 14px 12px;
}
.lasso-v2 .review-tabs-frame > #reviewTabs .nav-link:hover{ border-bottom-color:var(--line); }
.lasso-v2 .review-tabs-frame > #reviewTabs .nav-link.active{ font-weight:800; }
.lasso-v2 .review-tabs-frame > #reviewTabs .nav-link:focus-visible{
  outline:2px solid var(--brand-red); outline-offset:-2px; border-radius:6px;
}
/* Tick = "this section has details to review". It is a data-completeness
   signal, not a claim that the user has read the section. */
.lasso-v2 .rev-tab-check{ font-size:11px; color:var(--green); flex:none; }
.lasso-v2 .rev-tab-check.is-empty{ color:#C9CED5; }

/* Section eyebrow inside each pane — names the current section when the tab
   strip has been scrolled out of view. */
.lasso-v2 .rev-pane-title{
  font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted); margin-bottom:12px;
}
.lasso-v2 .review-hint{
  display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--muted);
  margin:0 1.25rem 1.25rem; padding-top:14px; border-top:1px solid var(--line);
}
.lasso-v2 .review-hint i{ color:var(--green); font-size:12px; }
.lasso-v2 .review-hint i.fa-circle-info{ color:var(--muted); }
.lasso-v2 .review-subhead{ font-size:13.5px; color:var(--muted); margin:-.35rem 0 .25rem; }

/* Head actions are deliberately quiet so the checkout CTA stays the only
   high-emphasis action on the page. */
.lasso-v2 .review-head-btn{ font-size:12.5px!important; font-weight:700!important; }
.lasso-v2 .review-head-edit{
  background:#fff!important; color:var(--brand-red-dark)!important;
  border:1.5px solid #F3CDCB!important; box-shadow:none!important;
}
.lasso-v2 .review-head-edit:hover{ background:#FDECEA!important; color:var(--brand-red-dark)!important; }

/* ---- Wizard step heading on a phone ------------------------------------
   ele_page_heading lays the title and its actions out as a form-inline row and
   relies on the col-lg-* halves to separate them. On a phone the halves stack
   with no spacing of their own: the two Review actions sat 8px under the title,
   indented to wherever the row happened to leave them, and .review-subhead's
   -.35rem top margin then pulled the subtitle up INTO the buttons — a 1.6px
   overlap. Stack the three deliberately, all on the page's left edge.

   The breakpoint is 992, not 768: the two halves are col-lg-6, so they stack
   from 991.98px down and the crammed spacing starts there, not at phone width.

   NB: the wrapper stays a block box. Making it a column flex container looks
   tempting, but the groups carry col-md-12 (flex:1 1 100%) and in a column
   container that basis is read as HEIGHT — each group ballooned to 320px. */
@media(max-width:991.98px){
  .lasso-v2 .customer-step-layout .form-row.form-inline.underline > .form-group{
    display:flex; flex-wrap:wrap; align-items:center; gap:8px;
    width:100%; max-width:100%; margin:0;
    justify-content:flex-start; text-align:left;
  }
  .lasso-v2 .customer-step-layout .form-row.form-inline.underline > .form-group + .form-group{
    margin-top:12px;
  }
  .lasso-v2 .review-subhead{ margin-top:12px; }
}

/* Mobile: the plan summary moves above the tabbed detail and the checkout
   button is pinned, so neither is buried under seven sections of review copy. */
.lasso-v2 .review-mobile-cta{ display:none; }
@media(max-width:991px){
  .lasso-v2 .review-checkout-row{ display:flex; flex-wrap:wrap; }
  .lasso-v2 .review-checkout-row > .col-lg-4{ order:-1; }
  .lasso-v2 .review-checkout-row > .col-lg-8{ order:0; }
  /* the pinned bar carries the action, so the in-card duplicate is dropped */
  .lasso-v2 .review-checkout-cta .btn-pay-review,
  .lasso-v2 .review-checkout-cta .cta-stripe-note,
  .lasso-v2 .review-checkout-cta .cta-plan-feats{ display:none; }
  .lasso-v2 .review-tabs-frame > #reviewTabContent{ min-height:0; }
  /* Fixed, not sticky: sticky stops pinning once .formDiv scrolls past, which
     is exactly when the customer is deepest into the review copy. */
  .lasso-v2 .review-mobile-cta{
    display:block; position:fixed; left:0; right:0; bottom:0; z-index:1030;
    background:#fff; border-top:1px solid var(--line); margin:0; padding:12px 16px;
    box-shadow:0 -6px 18px rgba(20,25,35,.08);
  }
  .lasso-v2 .review-mobile-cta .btn{ width:100%; box-shadow:none; }
  /* keep the last of the page clear of the pinned bar — on the step layout AND
     at page level, since footer.php renders outside <main> (same reason as the
     wizard action bar's clearance above). The CTA is only rendered when there
     is something to buy, so :has() keys on it: an already-subscribed review
     page gets no bar and needs no clearance. */
  .lasso-v2 .review-step-layout{ padding-bottom:24px; }
  body.lasso-v2:has(.review-mobile-cta) .lv2-shell{ padding-bottom:84px; }
}
/* review-pane tables (hours / geo summary) — Bootstrap .table isn't on the clean layout */
.lasso-v2 .table{ width:100%; border-collapse:collapse; font-size:13.5px; color:var(--text); margin-bottom:0; }
.lasso-v2 .table th, .lasso-v2 .table td{ padding:8px 12px; border-bottom:1px solid var(--line); text-align:left; vertical-align:middle; }
/* Column headers sit one step up from the 11px muted grey they started at:
   12px on --ink. At 11px in --muted the header row read lighter than the data
   under it, so a dense table (the invoices index especially) had no visible
   top edge to scan from. Weight was already 700 — Inter has no headroom past
   it that reads as "bolder", so the size and the colour are what carry it.
   Kept in step with the `.tbl` header rule further down. */
.lasso-v2 .table thead th{ font-weight:700; font-size:12px; letter-spacing:.05em; text-transform:uppercase; color:var(--ink); background:#F7F8FA; }
.lasso-v2 .table-sm th, .lasso-v2 .table-sm td{ padding:6px 10px; }
.lasso-v2 .table-striped tbody tr:nth-of-type(odd){ background:#FAFBFC; }
.lasso-v2 .table tbody tr:last-child td, .lasso-v2 .table tbody tr:last-child th{ border-bottom:0; }
/* …except when the table asked to be bordered. Dropping the last line suits a
   table that sits inside a bordered card, which is what the rule above was for.
   The legacy boards are bare `table-bordered` grids with no card around them, so
   it just left every table on the HBU big board open at the bottom — 19 of them
   on that page alone. The bordered variant keeps its closing line. */
.lasso-v2 .table.table-bordered tbody tr:last-child td,
.lasso-v2 .table.table-bordered tbody tr:last-child th{ border-bottom:1px solid var(--line); }
/* review-pane column sizing (panes live outside a .card, so the card-row shim
   doesn't apply) — give the summary rows real proportions + full width */
.lasso-v2 #reviewTabContent .row{ align-items:flex-start; }
@media(min-width:768px){
  .lasso-v2 #reviewTabContent .row > .col-lg-5{ flex:41 1 0; min-width:0; }
  .lasso-v2 #reviewTabContent .row > .col-lg-7{ flex:59 1 0; min-width:0; }
  .lasso-v2 #reviewTabContent .row > .col-lg-6{ flex:0 1 calc(50% - 6px); max-width:calc(50% - 6px); min-width:0; }
  .lasso-v2 #reviewTabContent .row > .col-md-3{ flex:1 1 0; min-width:0; }
  .lasso-v2 #reviewTabContent .row > .col-md-9{ flex:3 1 0; min-width:0; }
}
/* payment-options review tiles — equal-size compact cards (were min-width so the
   longest label stretched one wider than the rest) */
.lasso-v2 #rev-payments-pane .card{ width:156px; margin:0; padding:0; border:1px solid var(--line); border-radius:12px; box-shadow:var(--card-shadow); }
.lasso-v2 #rev-payments-pane .card .card-body{ padding:14px 10px; }

/* badges */
.lasso-v2 .badge{
  display:inline-flex; align-items:center; gap:6px; font-weight:700;
  font-size:11.5px; padding:5px 12px; border-radius:999px; line-height:1.4;
}
.lasso-v2 .badge i{ width:6px; height:6px; border-radius:50%; font-style:normal; }
.lasso-v2 .b-green{ background:#E6F6EC; color:var(--green); } .lasso-v2 .b-green i{ background:var(--green); }
.lasso-v2 .b-amber{ background:#FFF3E0; color:#B4690E; }     .lasso-v2 .b-amber i{ background:#E8912B; }
.lasso-v2 .b-blue{ background:#E7F0FE; color:var(--blue); }   .lasso-v2 .b-blue i{ background:var(--blue); }
.lasso-v2 .b-red{ background:#FDECEA; color:var(--brand-red); } .lasso-v2 .b-red i{ background:var(--brand-red); }
.lasso-v2 .b-neutral{ background:#F1F3F5; color:var(--muted); } .lasso-v2 .b-neutral i{ background:#AEB4BC; }

/* Bootstrap badge variants. The `.badge` base above gave every badge the pill
   shape but none of them a colour, so `badge-danger` and `badge-secondary` came
   out identical — an error in the log list looked exactly like an info row.
   184 uses across templates (76 secondary, 30 danger, 24 warning, 23 info).
   Mapped onto the b-* tints above so they stay in the same design system.
   danger is the exception: solid rather than tinted, because its whole job is
   to be findable while scanning a long list of log rows. */
.lasso-v2 .badge-danger{ background:var(--brand-red); color:#fff; }
.lasso-v2 .badge-danger i{ background:#fff; }
.lasso-v2 .badge-warning{ background:#FFF3E0; color:#B4690E; }
.lasso-v2 .badge-warning i{ background:#E8912B; }
.lasso-v2 .badge-info{ background:#E7F0FE; color:var(--blue); }
.lasso-v2 .badge-info i{ background:var(--blue); }
.lasso-v2 .badge-success{ background:#E6F6EC; color:var(--green); }
.lasso-v2 .badge-success i{ background:var(--green); }
.lasso-v2 .badge-secondary{ background:#F1F3F5; color:var(--muted); }
.lasso-v2 .badge-secondary i{ background:#AEB4BC; }
.lasso-v2 .badge-primary{ background:#E7F0FE; color:var(--blue); }
.lasso-v2 .badge-primary i{ background:var(--blue); }
.lasso-v2 .badge-light{ background:#F1F3F5; color:var(--text); }
.lasso-v2 .badge-dark{ background:var(--ink); color:#fff; }
.lasso-v2 .badge-dark i{ background:#fff; }

/* Status pill that is also a link — the per-traffic-source cells on
   /hnc-campaigns. Every pill in that grid opens the same campaign-validation
   page for its partner, so the underline was pure noise struck through the pill;
   the pointer and the hover ring say "clickable" without spending a row of
   pixels on it. */
.lasso-v2 a.partner-status,
.lasso-v2 a.partner-status:hover{ text-decoration:none; }
.lasso-v2 a.partner-status .badge{ transition:box-shadow .15s ease, filter .15s ease; }
.lasso-v2 a.partner-status:hover .badge{ box-shadow:0 0 0 2px rgba(20,25,35,.12); filter:brightness(.97); }
.lasso-v2 a.partner-status:focus-visible .badge{ box-shadow:0 0 0 3px rgba(47,111,214,.35); outline:none; }

/* Legacy colored_label pills.
   templates/element/colored_label.php emits Bootstrap utilities
   (`px-1 py-1 text-white bg-success|bg-danger|…`) and is used on 42 templates.
   Under .lasso-v2 those utilities are unstyled, so the label collapsed to bare
   bold text. Rather than restyling `.bg-*` globally — which would also hijack the
   "Results Filtered" banner in element('search') and any other bg-utility use —
   the element carries a dedicated `clsColoredLabel` hook and only that is themed.
   Un-migrated pages keep Bootstrap's original look untouched. */
.lasso-v2 .clsColoredLabel > span{
  display:inline-flex; align-items:center; gap:6px;
  font-weight:700; font-size:11.5px; line-height:1.4;
  padding:5px 12px!important; border-radius:999px;
  background:#F1F3F5!important; color:var(--muted)!important;
}
.lasso-v2 .clsColoredLabel > span.bg-success{ background:#E6F6EC!important; color:var(--green)!important; }
.lasso-v2 .clsColoredLabel > span.bg-danger{  background:#FDECEA!important; color:var(--brand-red)!important; }
.lasso-v2 .clsColoredLabel > span.bg-warning{ background:#FFF3E0!important; color:#B4690E!important; }
.lasso-v2 .clsColoredLabel > span.bg-info{    background:#E7F0FE!important; color:var(--blue)!important; }
.lasso-v2 .clsColoredLabel > span.bg-primary{ background:#FDECEA!important; color:var(--brand-red)!important; }

/* Bootstrap progress bar — used by long-running job rows (Cron Jobs) and had no v2
   rule, so the track and fill were both invisible and only the "62%" text showed. */
.lasso-v2 .progress{
  height:8px; background:var(--line); border-radius:999px; overflow:hidden;
  display:flex; margin:2px 0 6px;
}
.lasso-v2 .progress-bar{
  background:var(--teal); color:transparent; font-size:0;
  display:flex; align-items:center; justify-content:center;
  transition:width .3s ease;
}

/* data table.
   overflow-x is auto, not hidden. `overflow:hidden` was here to clip the table
   to the 14px corner radius, but it also swallowed any table wider than its
   container: the outer scroll wrapper measured scrollWidth === clientWidth and
   offered no scrollbar, so on a narrow window the trailing columns — Actions,
   on the customers list — were cut off with no way to reach them. overflow-y
   stays hidden, which is what actually clips the corners. */
.lasso-v2 .tbl{ border:1px solid var(--line); border-radius:14px; overflow-x:auto; overflow-y:hidden; }
.lasso-v2 .tbl table,
.lasso-v2 table.tbl{ width:100%; border-collapse:collapse; font-size:13.5px; }
.lasso-v2 .tbl thead th,
.lasso-v2 table.tbl thead th{
  text-align:left; padding:12px 16px; background:#F7F8FA; color:var(--ink);
  /* matches the `.table thead th` bump above — the two header treatments are
     used side by side on the same pages, so they move together */
  font-weight:700; font-size:12px; letter-spacing:.06em; text-transform:uppercase;
  border-bottom:1px solid var(--line);
}
.lasso-v2 .tbl tbody td,
.lasso-v2 table.tbl tbody td{ padding:13px 16px; border-bottom:1px solid #EEF0F3; }
.lasso-v2 .tbl tbody tr:last-child td,
.lasso-v2 table.tbl tbody tr:last-child td{ border-bottom:0; }
.lasso-v2 .tbl tbody tr:hover,
.lasso-v2 table.tbl tbody tr:hover{ background:#FAFBFC; }
.lasso-v2 .oid{ font-weight:700; color:var(--ink); }

/* KPI cards */
.lasso-v2 .kpi{
  background:#fff; border:1px solid var(--line); border-radius:16px;
  padding:18px 20px; box-shadow:var(--card-shadow); position:relative; overflow:hidden;
}
.lasso-v2 .kpi .accent{ position:absolute; left:0; top:0; bottom:0; width:4px; background:var(--blue); }
.lasso-v2 .kpi .lbl{ font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
.lasso-v2 .kpi .val{ font-family:'Montserrat','Inter',sans-serif; font-weight:900; font-size:30px; color:var(--ink); margin:8px 0 6px; }
.lasso-v2 .kpi .delta{ font-size:12px; color:var(--muted); background:#F1F3F5; padding:3px 9px; border-radius:999px; }

/* tabs / segmented / stepper */
.lasso-v2 .tabs{ display:flex; gap:4px; border-bottom:1px solid var(--line); }
.lasso-v2 .tab{
  padding:10px 16px; font-size:14px; font-weight:600; color:var(--muted); cursor:pointer;
  border-bottom:2px solid transparent; margin-bottom:-1px; background:none;
  border-top:0; border-left:0; border-right:0; font-family:inherit;
}
.lasso-v2 .tab.active{ color:var(--brand-red); border-bottom-color:var(--brand-red); }
.lasso-v2 .seg{ display:inline-flex; background:#F1F3F5; border:1px solid var(--line); border-radius:11px; padding:3px; }
.lasso-v2 .seg button{
  border:0; background:none; font-family:inherit; font-size:13px; font-weight:600;
  color:var(--muted); padding:7px 15px; border-radius:8px; cursor:pointer;
}
.lasso-v2 .seg button.on{ background:#fff; color:var(--ink); box-shadow:0 1px 3px rgba(0,0,0,.12); }
.lasso-v2 .stepper{ display:flex; align-items:center; gap:0; }
.lasso-v2 .stp{ display:flex; align-items:center; gap:9px; }
.lasso-v2 .stp .num{
  width:30px; height:30px; border-radius:50%; border:2px solid var(--line);
  display:flex; align-items:center; justify-content:center; font-weight:700;
  font-size:12.5px; color:var(--muted); background:#fff;
}
.lasso-v2 .stp.done .num{ background:#E6F6EC; border-color:#BEE6CE; color:var(--green); }
.lasso-v2 .stp.active .num{ background:var(--brand-red); border-color:var(--brand-red); color:#fff; }
.lasso-v2 .stp .lbl{ font-size:13px; font-weight:600; color:var(--muted); }
.lasso-v2 .stp.active .lbl{ color:var(--ink); font-weight:700; }
.lasso-v2 .stp.active .num{ box-shadow:0 0 0 4px rgba(232,54,43,.15); }
.lasso-v2 .stp .line{ width:40px; height:2px; background:var(--line); margin:0 10px; }

/* wizard "Setup progress" header — sits above the vertical stepper in the
   customer-setup steps card (per wizard-basic-info-redesign mockup). */
.lasso-v2 .stepper-progress{ margin-bottom:18px; }
.lasso-v2 .stepper-progress .sp-t{ font-size:11.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); }
.lasso-v2 .stepper-progress .sp-bar{ height:6px; border-radius:5px; background:#EDEFF2; margin-top:9px; overflow:hidden; }
.lasso-v2 .stepper-progress .sp-bar i{ display:block; height:100%; background:linear-gradient(90deg,var(--brand-red),#ff6a5f); border-radius:5px; }
.lasso-v2 .stepper-progress .sp-p{ font-size:12px; color:var(--muted); margin-top:7px; }
.lasso-v2 .stepper-progress .sp-current{ display:none; font-size:13.5px; font-weight:700; color:var(--ink); margin-top:6px; }

/* The three wizard columns must start on the same line — .lasso-v2 .row centers
   its columns, which floats the shorter ones down. */
.lasso-v2 .customer-step-layout > .row{ align-items:flex-start; }

/* Mobile (<768px, where the 3-column layout stacks): the full 10-step list
   otherwise lands at the top of the page above the form. Collapse it to just
   the progress bar + the current step name so the wizard opens on the actual
   step content instead of the whole checklist. */
@media (max-width: 767.98px){
  .lasso-v2 .customer-step-layout .stepper{ display:none; }
  .lasso-v2 .stepper-progress{ margin-bottom:0; }
  .lasso-v2 .stepper-progress .sp-current{ display:block; }
}

/* ============================================================================
   AUTH — split-screen shell (marketing / login / register)
   Reused by: /login two-step (lasso_login_page) via element auth/split_shell.
   Later: register-role, welcome-modal. Values copied verbatim from
   resources/new-designs/completed/get-started-redesign.html. All scoped under .lasso-v2.
   ========================================================================== */
.lasso-v2 .auth-split{
  display:grid; grid-template-columns:1.05fr 1fr; min-height:520px;
  background:#fff; border:1px solid #EAEDF0; border-radius:20px; overflow:hidden;
  /* Full width with the standard gutter, same as every other page in the app.
     Capped at 1240px earlier on 2026-08-17 while the site-wide column rule was
     in force; that rule was reverted the same day and this followed it back. */
  box-shadow:0 20px 50px rgba(20,25,35,.14);
  max-width:none; margin:24px var(--lm-gutter);
}
.lasso-v2 .auth-panel{
  background:linear-gradient(155deg,#232A31 0%,#1A2026 60%,#14181D 100%);
  color:#fff; padding:56px 50px; position:relative; overflow:hidden;
  display:flex; flex-direction:column; justify-content:center;
}
.lasso-v2 .auth-panel::before{ content:""; position:absolute; top:-90px; right:-90px; width:280px; height:280px; border-radius:50%; background:radial-gradient(circle,rgba(232,54,43,.28),transparent 68%); }
.lasso-v2 .auth-panel::after{ content:""; position:absolute; bottom:-70px; left:-40px; width:220px; height:220px; border-radius:50%; background:radial-gradient(circle,rgba(23,162,184,.22),transparent 68%); }
/* Content is centred in the panel and allowed to use its width. It used to be
   pinned to ~420px, which was right when the shell was capped at 1080px and
   leaves half the panel empty now that it is full width. */
.lasso-v2 .auth-panel-inner{ position:relative; z-index:1; max-width:620px; margin:0 auto; width:100%; }
.lasso-v2 .auth-eyebrow{ font-size:12px; font-weight:700; letter-spacing:.22em; color:var(--brand-red); text-transform:uppercase; margin:0 0 14px; }
.lasso-v2 .auth-panel h1{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:clamp(28px,2.6vw,42px); line-height:1.12; margin:0 0 16px; color:#fff; }
.lasso-v2 .auth-panel h1 em{ font-style:normal; color:var(--brand-red); }
.lasso-v2 .auth-panel-lead{ color:#B6BEC7; font-size:15.5px; line-height:1.6; max-width:52ch; margin-bottom:30px; }
.lasso-v2 .auth-benefits{ list-style:none; display:flex; flex-direction:column; gap:14px; margin:0; padding:0; }
.lasso-v2 .auth-benefits li{ display:flex; align-items:flex-start; gap:12px; font-size:14.5px; color:#DCE1E7; }
.lasso-v2 .auth-check{ flex:none; width:22px; height:22px; border-radius:50%; background:rgba(23,162,184,.18); color:var(--teal); display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:900; margin-top:1px; }

/* Proof row closing the brand panel — opt-in per page via split_shell's $proof. */
.lasso-v2 .auth-proof{ margin-top:32px; padding-top:24px; border-top:1px solid rgba(255,255,255,.14); display:flex; gap:30px; flex-wrap:wrap; }
.lasso-v2 .auth-proof b{ display:block; font-family:'Montserrat','Inter',sans-serif; font-weight:900; font-size:22px; color:#fff; }
.lasso-v2 .auth-proof span{ font-size:11.5px; color:#9AA3AD; letter-spacing:.03em; text-transform:uppercase; }

.lasso-v2 .auth-form-side{ padding:56px 54px; display:flex; flex-direction:column; justify-content:center; background:#fff; }
/* The submit button is the one thing on this page the visitor has to hit, and
   it was rendering 29px tall — a thin strip under two 34px inputs. The login
   page is a hybrid: v2 markup inside the legacy layout, so it still loads
   app.css and its `.btn{ padding:.35rem !important }`. Hence !important here —
   without it the padding never lands. */
.lasso-v2 .auth-form-side form .btn-primary{
  padding:15px 22px !important; font-size:15px !important; border-radius:11px;
}
.lasso-v2 .auth-form-card{ max-width:440px; width:100%; margin:0 auto; }
.lasso-v2 .auth-form-card h2{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:27px; color:var(--ink); margin:0 0 8px; }
.lasso-v2 .auth-form-card .sub{ color:var(--muted); font-size:14.5px; margin-bottom:26px; line-height:1.5; }
/* icon-input goes full width inside the auth card (override .inp max-width:320px) */
.lasso-v2 .auth-form-card .inp{ max-width:100%; }

.lasso-v2 .auth-steps{ display:flex; gap:6px; margin-bottom:26px; }
.lasso-v2 .auth-steps i{ height:5px; width:30px; border-radius:3px; background:var(--line); }
.lasso-v2 .auth-steps i.on{ background:var(--brand-red); }

.lasso-v2 .auth-label-row{ display:flex; justify-content:space-between; align-items:baseline; margin-bottom:8px; }
.lasso-v2 .auth-label-row .field-label{ margin-bottom:0; }
.lasso-v2 .auth-label-row a{ font-size:12.5px; color:var(--teal-dark); text-decoration:none; font-weight:600; }
.lasso-v2 .auth-label-row a:hover{ text-decoration:underline; }

.lasso-v2 .auth-back{ display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--muted); text-decoration:none; font-weight:600; margin-bottom:20px; }
.lasso-v2 .auth-back:hover{ color:var(--ink); }

.lasso-v2 .auth-helper{ display:flex; justify-content:space-between; align-items:center; margin-top:22px; font-size:13.5px; gap:10px; flex-wrap:wrap; }
.lasso-v2 .auth-helper a{ color:var(--teal-dark); text-decoration:none; font-weight:600; }
.lasso-v2 .auth-helper a:hover{ text-decoration:underline; }

.lasso-v2 .auth-trust{ display:flex; align-items:center; gap:8px; justify-content:center; color:var(--muted); font-size:12.5px; margin-top:24px; }

.lasso-v2 .auth-alert{ display:flex; gap:10px; align-items:flex-start; background:#FDECEA; border:1px solid #F5C6C0; color:#B02A1E; border-radius:11px; padding:11px 13px; font-size:13px; line-height:1.45; margin:16px 0; }
.lasso-v2 .auth-alert svg{ flex:none; margin-top:1px; }

.lasso-v2 .auth-captcha{ display:flex; justify-content:center; border:1px solid var(--line); border-radius:11px; background:#F9FAFB; padding:13px 15px; margin:16px 0 4px; }

/* password field with show/hide toggle */
.lasso-v2 .auth-pw{ position:relative; }
.lasso-v2 .auth-pw .inp input{ padding-right:46px; }
.lasso-v2 .auth-pw-toggle{ position:absolute; right:6px; top:50%; transform:translateY(-50%); background:none; border:0; cursor:pointer; color:var(--muted); padding:8px; display:flex; border-radius:8px; z-index:2; }
.lasso-v2 .auth-pw-toggle:hover{ color:var(--ink); background:#F1F3F5; }

/* "Keep me signed in" + forgot-password row on the password step */
.lasso-v2 .auth-remember-row{ display:flex; justify-content:space-between; align-items:center; margin-top:16px; font-size:13.5px; gap:12px; }
.lasso-v2 .auth-remember{ display:flex; align-items:center; gap:9px; color:var(--text); cursor:pointer; user-select:none; margin:0; font-weight:500; }
.lasso-v2 .auth-remember input{ width:17px; height:17px; accent-color:var(--brand-red); cursor:pointer; margin:0; }

/* Step-2 chip naming the account being signed into, with a "Change" escape */
.lasso-v2 .auth-whoami{ display:flex; align-items:center; gap:11px; background:#F7F9FA; border:1px solid var(--line); border-radius:12px; padding:11px 13px; margin-bottom:18px; }
.lasso-v2 .auth-whoami .av{ flex:none; width:34px; height:34px; border-radius:50%; background:#FDECEA; color:var(--brand-red); display:flex; align-items:center; justify-content:center; font-weight:800; font-size:13px; text-transform:uppercase; }
.lasso-v2 .auth-whoami .who{ flex:1; min-width:0; }
.lasso-v2 .auth-whoami .who b{ display:block; font-size:13.5px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lasso-v2 .auth-whoami .who span{ font-size:11.5px; color:var(--muted); }
.lasso-v2 .auth-whoami a{ background:none; border:0; color:var(--teal-dark); font-weight:700; font-size:12.5px; text-decoration:none; padding:6px 8px; border-radius:8px; flex:none; }
.lasso-v2 .auth-whoami a:hover{ background:#EAF6F8; }

/* "or sign in with" rule + the social buttons under it */
.lasso-v2 .auth-or{ display:flex; align-items:center; gap:14px; margin:24px 0; color:#A6AEB8; font-size:12px; }
.lasso-v2 .auth-or::before,.lasso-v2 .auth-or::after{ content:""; height:1px; background:var(--line); flex:1; }
.lasso-v2 .auth-socials{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.lasso-v2 .auth-social{ display:flex; align-items:center; justify-content:center; gap:9px; border:1.5px solid var(--line); background:#fff; border-radius:12px; padding:12px; font-size:14px; font-weight:600; color:var(--ink); cursor:pointer; font-family:inherit; transition:.16s; text-decoration:none; }
.lasso-v2 .auth-social:hover{ border-color:#C9CFD6; background:#FAFBFC; color:var(--ink); text-decoration:none; }
.lasso-v2 .auth-social svg{ flex:none; }
/* Shown when a social provider is clicked before OAuth is wired up. */
.lasso-v2 .auth-social-soon{ display:none; align-items:flex-start; gap:9px; background:#F7F9FA; border:1px solid var(--line); color:#4B535C; border-radius:11px; padding:11px 13px; font-size:12.5px; line-height:1.5; margin-top:12px; }
.lasso-v2 .auth-social-soon.on{ display:flex; }
.lasso-v2 .auth-social-soon svg{ flex:none; margin-top:1px; color:var(--teal-dark); }

/* One labelled field inside an auth card */
.lasso-v2 .auth-field{ margin-bottom:16px; }
.lasso-v2 .auth-field:last-child{ margin-bottom:0; }

/* Two fields sharing a row (first / last name on register) */
.lasso-v2 .auth-row-2{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
@media(max-width:480px){ .lasso-v2 .auth-row-2{ grid-template-columns:1fr; gap:0; } }

/* Password requirements, ticking green as they are satisfied. Shared by register
   and change-password so the same rules are described the same way in both. */
.lasso-v2 .pw-rules{ list-style:none; display:flex; flex-direction:column; gap:7px; margin:11px 0 0; padding:0; }
.lasso-v2 .pw-rules li{ display:flex; align-items:flex-start; gap:9px; font-size:12.5px; color:var(--muted); line-height:1.45; transition:color .16s; }
.lasso-v2 .pw-rules li .tick{
  flex:none; width:17px; height:17px; border-radius:50%; border:1.5px solid var(--line);
  display:flex; align-items:center; justify-content:center; color:transparent;
  font-size:10px; font-weight:900; margin-top:1px; transition:.16s;
}
.lasso-v2 .pw-rules li.is-met{ color:#3F4750; }
.lasso-v2 .pw-rules li.is-met .tick{ background:var(--green,#1E9E62); border-color:var(--green,#1E9E62); color:#fff; }
/* Checked server-side on submit, so it can never tick as you type. A dashed
   outline says "we will check this" rather than pretending to be a live rule. */
.lasso-v2 .pw-rules li.pw-rule-server{ color:#8A929C; }
.lasso-v2 .pw-rules li.pw-rule-server .tick{ border-style:dashed; }

.lasso-v2 .pw-strength{ display:flex; gap:5px; margin-top:12px; }
.lasso-v2 .pw-strength i{ height:4px; flex:1; border-radius:3px; background:var(--line); transition:background .2s; }
.lasso-v2 .pw-strength.s1 i:nth-child(1){ background:var(--brand-red); }
.lasso-v2 .pw-strength.s2 i:nth-child(-n+2){ background:#E8A33B; }
.lasso-v2 .pw-strength.s3 i:nth-child(-n+3){ background:#7FB93F; }
.lasso-v2 .pw-strength.s4 i{ background:var(--green,#1E9E62); }
.lasso-v2 .pw-strength-txt{ font-size:11.5px; color:var(--muted); margin-top:7px; font-weight:600; }

.lasso-v2 .auth-legal{ font-size:12px; color:var(--muted); line-height:1.55; margin-top:18px; }
.lasso-v2 .auth-legal a{ color:var(--teal-dark); font-weight:600; text-decoration:none; }
.lasso-v2 .auth-legal a:hover{ text-decoration:underline; }

/* Field-level validation errors inside an auth card.
   background and padding are reset explicitly, not by accident: app.css carries an
   unscoped legacy `.error-message{ padding-left:10px; color:white; background-color:red }`,
   and the auth pages load it. Setting only the colour here left that solid red block
   underneath — red text on a red slab, sitting over the password field and
   unreadable. Reported 2026-08-17. Any rule that recolours .error-message has to
   clear the background too. */
.lasso-v2 .auth-form-card .error-message,
.lasso-v2 .auth-form-card .text-danger{
  display:block; margin-top:7px; font-size:12.5px; font-weight:600;
  color:var(--brand-red); background:none; padding:0;
}
.lasso-v2 .auth-form-card .error-message ul,
.lasso-v2 .auth-form-card .text-danger ul{ margin:4px 0 0; padding-left:16px; }

/* "New to Lasso? Create an account" foot of the card */
.lasso-v2 .auth-signup{ text-align:center; font-size:13.5px; color:var(--muted); margin-top:22px; padding-top:20px; border-top:1px solid var(--line); }
.lasso-v2 .auth-signup a{ color:var(--teal-dark); font-weight:700; text-decoration:none; }
.lasso-v2 .auth-signup a:hover{ text-decoration:underline; }

/* Flash messages rendered inside the auth card echo the .auth-alert look */
.lasso-v2 .auth-form-card .alert{ border:1px solid transparent; border-radius:11px; font-size:13px; line-height:1.45; }
.lasso-v2 .auth-form-card .alert-danger{ background:#FDECEA; border-color:#F5C6C0; color:#B02A1E; }
.lasso-v2 .auth-form-card .alert-success{ background:#E6F6EC; border-color:#BEE6CE; color:#188047; }

/* responsive: stack to a compact hero above the form */
@media(max-width:980px){
  .lasso-v2 .auth-split{ grid-template-columns:1fr; margin:16px auto; border-radius:16px; }
  .lasso-v2 .auth-panel{ padding:34px 30px 30px; }
  .lasso-v2 .auth-panel h1{ font-size:24px; }
  .lasso-v2 .auth-eyebrow{ margin-top:0; }
  .lasso-v2 .auth-panel-lead{ margin-bottom:0; font-size:13.5px; }
  .lasso-v2 .auth-benefits{ display:none; }
  /* Same reasoning as the benefits list: the panel collapses to a compact hero
     above the form, and the proof row is supporting detail, not the task. */
  .lasso-v2 .auth-proof{ display:none; }
  .lasso-v2 .auth-form-side{ padding:30px 26px 36px; }
}
@media(max-width:480px){
  .lasso-v2 .auth-form-card h2{ font-size:22px; }
  .lasso-v2 .auth-helper{ justify-content:flex-start; }
  .lasso-v2 .auth-socials{ grid-template-columns:1fr; }
  .lasso-v2 .auth-remember-row{ flex-direction:column; align-items:flex-start; gap:10px; }
}

/* ============================================================================
   DASHBOARD / PORTAL HOME  (/welcome for CPORTAL) — greeting, action cards,
   plan-usage cards. Values from resources/new-designs/completed/dashboard-redesign.html.
   The dark bar + red nav come from backend_header (preserved); this styles the
   page body only. All scoped under .lasso-v2.
   ========================================================================== */
.lasso-v2 .dash-hello{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:32px; color:var(--ink); letter-spacing:-.01em; margin:0; }
.lasso-v2 .dash-sub{ color:var(--muted); font-size:15px; margin-top:6px; }
/* Breathing room between the greeting and the first section label. padding-bottom
   (not margin) so it cannot margin-collapse with the section label's margin-top.
   Was 42px, giving ~76px total with that margin — which read as designed but put
   the "Choose Your Package" CTA below the fold at 1080px, on the one screen whose
   entire job is getting the customer to that button. 18px keeps the greeting
   distinct without costing the fold. */
.lasso-v2 .dash-greeting{ padding-bottom:18px; }
.lasso-v2 .section-label{ font-weight:700; font-size:13px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin:34px 0 16px; }

.lasso-v2 .dash-actions{ display:grid; grid-template-columns:repeat(4,1fr); gap:16px; }
.lasso-v2 .dash-action{ display:flex; flex-direction:column; gap:14px; background:#fff; border:1px solid var(--line); border-radius:16px; padding:20px; cursor:pointer; transition:.16s; text-decoration:none; box-shadow:var(--card-shadow); color:inherit; }
.lasso-v2 .dash-action:hover{ transform:translateY(-3px); border-color:#D3D8DE; box-shadow:0 10px 26px rgba(20,25,35,.1); }
.lasso-v2 .dash-action .icon{ width:44px; height:44px; border-radius:12px; display:flex; align-items:center; justify-content:center; flex:none; font-size:18px; }
.lasso-v2 .dash-action .ic-red{ background:#FDECEA; color:var(--brand-red); }
.lasso-v2 .dash-action .ic-teal{ background:#E2F4F7; color:var(--teal-dark); }
.lasso-v2 .dash-action .ic-slate{ background:#E9EDF2; color:#4A5561; }
.lasso-v2 .dash-action .ic-violet{ background:#EEEBFB; color:var(--violet); }
.lasso-v2 .dash-action h3{ font-size:15.5px; font-weight:700; color:var(--ink); margin:0; }
.lasso-v2 .dash-action p{ font-size:12.5px; color:var(--muted); margin-top:3px; line-height:1.4; }
.lasso-v2 .dash-action .go{ margin-top:auto; display:flex; align-items:center; gap:6px; font-size:12.5px; font-weight:700; color:var(--brand-red); }
.lasso-v2 .dash-action.primary{ background:linear-gradient(160deg,#E8362B,#C42A20); border-color:transparent; }
.lasso-v2 .dash-action.primary .icon{ background:rgba(255,255,255,.18); color:#fff; }
.lasso-v2 .dash-action.primary h3{ color:#fff; }
.lasso-v2 .dash-action.primary p{ color:rgba(255,255,255,.85); }
.lasso-v2 .dash-action.primary .go{ color:#fff; }

.lasso-v2 .usage{ display:grid; grid-template-columns:1fr 1fr; gap:16px; max-width:760px; }
.lasso-v2 .u-card{ background:#fff; border:1px solid var(--line); border-radius:16px; padding:20px 22px; box-shadow:var(--card-shadow); }
.lasso-v2 .u-head{ display:flex; align-items:center; gap:12px; }
.lasso-v2 .u-icon{ width:40px; height:40px; border-radius:11px; display:flex; align-items:center; justify-content:center; flex:none; font-size:16px; }
.lasso-v2 .u-icon.loc{ background:#E7F0FE; color:#2F6FD6; }
.lasso-v2 .u-icon.call{ background:#E6F6EC; color:#1F9D57; }
.lasso-v2 .u-meta .lbl{ font-size:13px; color:var(--muted); }
.lasso-v2 .u-meta .val{ font-size:20px; font-weight:800; color:var(--ink); margin-top:1px; }
.lasso-v2 .u-meta .val small{ font-size:13px; font-weight:600; color:var(--muted); }
.lasso-v2 .u-card .chev{ margin-left:auto; color:#B4BBC3; display:flex; }
.lasso-v2 .bar{ height:7px; border-radius:5px; background:#EDEFF2; margin:16px 0 9px; overflow:hidden; }
.lasso-v2 .bar i{ display:block; height:100%; border-radius:5px; }
.lasso-v2 .bar i.blue{ background:linear-gradient(90deg,#2F6FD6,#5B93EC); }
.lasso-v2 .bar i.green{ background:linear-gradient(90deg,#1F9D57,#41c07a); }
.lasso-v2 .bar i.amber{ background:linear-gradient(90deg,#E8912B,#f0b45f); }
.lasso-v2 .bar i.red{ background:linear-gradient(90deg,#E8362B,#ff6a5f); }
.lasso-v2 .u-foot{ display:flex; justify-content:space-between; font-size:12.5px; color:var(--muted); }
.lasso-v2 .u-foot b{ color:var(--text); font-weight:600; }

@media(max-width:980px){
  .lasso-v2 .dash-actions{ grid-template-columns:1fr 1fr; }
  .lasso-v2 .usage{ grid-template-columns:1fr; }
}
@media(max-width:560px){
  .lasso-v2 .dash-hello{ font-size:24px; }
  .lasso-v2 .dash-action{ padding:16px; }
}

/* ============================================================================
   BILLING HISTORY — summary tiles + payments table
   The tiles reuse .kpi, but hold names and dates rather than figures, so .val
   gets a text-sized variant. Everything else is prefixed bh- to keep generic
   words (.num, .tag) out of the global namespace.
   ========================================================================= */
.lasso-v2 .kpi .val.text{ font-size:19px; font-weight:800; line-height:1.25; margin:7px 0 4px; }
.lasso-v2 .kpi .cyc{ display:flex; justify-content:space-between; align-items:baseline; font-size:13px; margin-top:7px; }
.lasso-v2 .kpi .cyc span:first-child{ color:var(--muted); }
.lasso-v2 .kpi .cyc span:last-child{ font-weight:700; color:var(--ink); }
.lasso-v2 .bh-actions{ display:flex; justify-content:flex-end; margin:16px 0 22px; }
.lasso-v2 .bh-num{ text-align:right; font-variant-numeric:tabular-nums; font-weight:700; color:var(--ink); }
.lasso-v2 .bh-tag{
  display:inline-block; font-size:9.5px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--muted); background:#F1F3F5;
  border:1px solid var(--line); border-radius:5px; padding:2px 6px;
  margin-left:7px; vertical-align:middle;
}
.lasso-v2 .bh-dt-sub{ color:var(--muted); font-size:12px; }
.lasso-v2 .bh-empty{ text-align:center; padding:18px 20px 6px; }
.lasso-v2 .bh-empty .ico{ font-size:26px; margin-bottom:8px; opacity:.45; }
/* The legacy table washed the whole row for failed/pending payments. Keep that
   scannability at v2 weight: a tinted left edge instead of a full-row wash. */
.lasso-v2 .tbl tbody tr.row-failed td:first-child{ box-shadow:inset 3px 0 0 var(--brand-red); }
.lasso-v2 .tbl tbody tr.row-pending td:first-child{ box-shadow:inset 3px 0 0 #E8912B; }

/* ── Legacy report-board colour helpers (app.css parity) ──────────────────────
   The HNC/HIBU report boards colour their header cells and summary rows with
   app.css helpers (`lassobigBoardHeading`, `cls*Bkgrnd`) plus Bootstrap's
   `bg-*` background utilities, and pair them with `.text-white`. Neither app.css
   nor Bootstrap's CSS is loaded under .lasso-v2 (the layout pulls Bootstrap's JS
   only), so BOTH halves of that pairing have to be ported here — an earlier
   revision of this comment claimed `.text-white` was already available and it is
   not, which is what left the text half missing until it was added below. These
   restore the legacy pairing, .lasso-v2 scoped, so nothing changes for pages
   still on the old layout.
   Kept low-specificity on purpose: the `.clsColoredLabel > span.bg-*` pills
   above use !important and still win. */
.lasso-v2 .lassobigBoardHeading{ background-color:#58728D; color:#fff; padding:2px; text-align:center; }
.lasso-v2 .lassobigBoardSubHeading{ font-weight:bold; background-color:#f1f1f1; }

/* Legacy tables say how a cell should sit two ways: the presentational `align`
   attribute the boards were written with, and Bootstrap's `.text-*` utilities.
   `.lasso-v2 .table th, .lasso-v2 .table td` left-aligns every cell and outranks
   both, so every figure on the HBU/HNC boards drifted to the left of its column.
   Cost Analytics and Fulfillment Percentage read right-aligned in Jun and
   left-aligned after the migration, and the KPI tiles lost their centring.
   Both forms are restored one notch above that rule. The utilities come second
   so a cell carrying both — the KPI tiles are align="right" text-center — ends up
   centred, which is what it did before. */
.lasso-v2 .table th[align="left"],.lasso-v2 .table td[align="left"]{ text-align:left; }
.lasso-v2 .table th[align="center"],.lasso-v2 .table td[align="center"]{ text-align:center; }
.lasso-v2 .table th[align="right"],.lasso-v2 .table td[align="right"]{ text-align:right; }
.lasso-v2 .table th.text-left,.lasso-v2 .table td.text-left{ text-align:left; }
.lasso-v2 .table th.text-center,.lasso-v2 .table td.text-center{ text-align:center; }
.lasso-v2 .table th.text-right,.lasso-v2 .table td.text-right{ text-align:right; }
/* A title bar centres wherever it sits. The thead form is handled further down;
   the boards put theirs in a bare <tr>, where it was left-aligned. */
.lasso-v2 .table th.lassobigBoardHeading,
.lasso-v2 .table td.lassobigBoardHeading{ text-align:center; }

/* The four KPI tiles print their figure at Bootstrap's `display-3` with the
   percentage under it at `display-5`, a step app.css added. Neither stylesheet is
   loaded under .lasso-v2, so both fell back to the theme's h3/p — an 18px bold
   heading in the ink colour, where the board had a 4.5rem light figure in the
   tile's own colour. Ported at the legacy sizes, in the legacy face rather than
   the theme's Montserrat, and with the colour inherited from the cell so
   `text-success` / `clsWhiteText` / `clsDarkRedText` reach the figure again. */
.lasso-v2 .display-1,.lasso-v2 .display-2,.lasso-v2 .display-3,
.lasso-v2 .display-4,.lasso-v2 .display-5{
  font-family:inherit; font-weight:300; line-height:1.2; color:inherit;
}
.lasso-v2 .display-1{ font-size:6rem; }
.lasso-v2 .display-2{ font-size:5.5rem; }
.lasso-v2 .display-3{ font-size:4.5rem; }
.lasso-v2 .display-4{ font-size:3.5rem; }
.lasso-v2 .display-5{ font-size:2.5rem; line-height:1; margin-bottom:.1rem; }
.lasso-v2 .clsOrangeBkgrnd{ background-color:darkorange; }
.lasso-v2 .clsRedBackground{ background-color:#2e2e2e; }
.lasso-v2 .clsGreenBkgrnd{ background-color:#00B050; }
.lasso-v2 .clsBlueBkgrnd{ background-color:#3b81ba; }
.lasso-v2 .clsRedBkgrnd{ background-color:#cc2223; }
.lasso-v2 .clsLightRedBkgrnd{ background-color:#ffebea; }
.lasso-v2 .clsLightGreenBkgrnd{ background-color:#8bab43; }
.lasso-v2 .clsLightGreyBkgrnd{ background-color:#787276; }
.lasso-v2 .clsGreyBkgrnd{ background-color:#48494B; }
/* Bootstrap background utilities, only where a table cell/row relies on them
   for contrast against .text-white. */
.lasso-v2 td.bg-dark, .lasso-v2 th.bg-dark, .lasso-v2 tr.bg-dark{ background-color:#343a40; color:#fff; }
.lasso-v2 td.bg-success, .lasso-v2 th.bg-success, .lasso-v2 tr.bg-success{ background-color:#28a745; color:#fff; }
.lasso-v2 td.bg-danger, .lasso-v2 th.bg-danger, .lasso-v2 tr.bg-danger{ background-color:#dc3545; color:#fff; }
.lasso-v2 td.bg-warning, .lasso-v2 th.bg-warning, .lasso-v2 tr.bg-warning{ background-color:#ffc107; color:#212529; }
.lasso-v2 td.bg-primary, .lasso-v2 th.bg-primary, .lasso-v2 tr.bg-primary{ background-color:#007bff; color:#fff; }
/* CMPN_GLOBAL_STATUS_COLORS also emits `info` (in-progress / paused) and
   `secondary` (removed / not-allowed-on-google); without these the cell got no
   fill at all on /hibu-campaigns?search=remarks:Inactive and
   ?search=remarks:NOT-ALLOWED-ON-GOOGLE. */
.lasso-v2 td.bg-info, .lasso-v2 th.bg-info, .lasso-v2 tr.bg-info{ background-color:#17a2b8; color:#fff; }
.lasso-v2 td.bg-secondary, .lasso-v2 th.bg-secondary, .lasso-v2 tr.bg-secondary{ background-color:#6c757d; color:#fff; }
/* The other half of that pairing, which batch 5 missed. Legacy templates set the
   fill with a `bg-*` / `cls*Bkgrnd` class and the text with `.text-white` or an
   app.css `cls*Text` helper. Only the fills came over, so every saturated cell
   kept body-dark text — TOTAL REVENUE and GROSS PROFIT % on the HBU board, the
   HBU id column on /hibus-additionals — and any <a> inside one stayed link-blue
   and vanished outright (the Google Ads and Data/Settings columns on
   /hibu-campaigns, the order link on /hnc-google-ads).
   Anchors are listed explicitly: a colour set on a <td> never inherits into an
   <a>, which is why the cells that only contained links went fully invisible
   while the cells containing plain text merely looked wrong. */
.lasso-v2 .text-white,
.lasso-v2 .text-white a,
.lasso-v2 a.text-white{ color:#fff; }
.lasso-v2 .clsWhiteText,
.lasso-v2 .clsWhiteText a{ color:#fff; }
.lasso-v2 .clsGreenText{ color:green; }
.lasso-v2 .clsOrangeText{ color:orange; }
.lasso-v2 .clsRedText{ color:red; }
.lasso-v2 .clsDarkRedText{ color:darkred; }
/* Headings and paragraphs INSIDE a coloured cell need naming too. These classes
   are applied to the container and were written to work by inheritance, but the
   theme gives h1-h6 and p a colour of their own — and a direct rule always beats
   an inherited one, so the figure in a filled cell went back to dark ink while
   the cell around it stayed coloured. That is what left the dollar amounts on
   the welcome dashboard black on blue and black on green. */
.lasso-v2 .text-white h1,.lasso-v2 .text-white h2,.lasso-v2 .text-white h3,
.lasso-v2 .text-white h4,.lasso-v2 .text-white h5,.lasso-v2 .text-white h6,
.lasso-v2 .text-white p,
.lasso-v2 .clsWhiteText h1,.lasso-v2 .clsWhiteText h2,.lasso-v2 .clsWhiteText h3,
.lasso-v2 .clsWhiteText h4,.lasso-v2 .clsWhiteText h5,.lasso-v2 .clsWhiteText h6,
.lasso-v2 .clsWhiteText p{ color:#fff; }
.lasso-v2 .clsGreenText h1,.lasso-v2 .clsGreenText h2,.lasso-v2 .clsGreenText h3,
.lasso-v2 .clsGreenText h4,.lasso-v2 .clsGreenText h5,.lasso-v2 .clsGreenText h6,
.lasso-v2 .clsGreenText p{ color:green; }
.lasso-v2 .clsOrangeText h1,.lasso-v2 .clsOrangeText h2,.lasso-v2 .clsOrangeText h3,
.lasso-v2 .clsOrangeText h4,.lasso-v2 .clsOrangeText h5,.lasso-v2 .clsOrangeText h6,
.lasso-v2 .clsOrangeText p{ color:orange; }
.lasso-v2 .clsRedText h1,.lasso-v2 .clsRedText h2,.lasso-v2 .clsRedText h3,
.lasso-v2 .clsRedText h4,.lasso-v2 .clsRedText h5,.lasso-v2 .clsRedText h6,
.lasso-v2 .clsRedText p{ color:red; }
.lasso-v2 .clsDarkRedText h1,.lasso-v2 .clsDarkRedText h2,.lasso-v2 .clsDarkRedText h3,
.lasso-v2 .clsDarkRedText h4,.lasso-v2 .clsDarkRedText h5,.lasso-v2 .clsDarkRedText h6,
.lasso-v2 .clsDarkRedText p{ color:darkred; }
/* Safety net for the same class of bug on templates that filled a cell but never
   asked for white text: a link in a saturated cell takes the cell's contrast
   colour regardless. Underlined so it still reads as a link without the colour
   cue to distinguish it. */
.lasso-v2 td.bg-dark a, .lasso-v2 th.bg-dark a,
.lasso-v2 td.bg-success a, .lasso-v2 th.bg-success a,
.lasso-v2 td.bg-danger a, .lasso-v2 th.bg-danger a,
.lasso-v2 td.bg-primary a, .lasso-v2 th.bg-primary a,
.lasso-v2 td.bg-info a, .lasso-v2 th.bg-info a,
.lasso-v2 td.bg-secondary a, .lasso-v2 th.bg-secondary a,
.lasso-v2 td.clsBlueBkgrnd a, .lasso-v2 th.clsBlueBkgrnd a,
.lasso-v2 td.clsRedBkgrnd a, .lasso-v2 th.clsRedBkgrnd a,
.lasso-v2 td.clsGreenBkgrnd a, .lasso-v2 th.clsGreenBkgrnd a,
.lasso-v2 td.clsGreyBkgrnd a, .lasso-v2 th.clsGreyBkgrnd a,
.lasso-v2 td.clsLightGreyBkgrnd a, .lasso-v2 th.clsLightGreyBkgrnd a,
.lasso-v2 td.clsLightGreenBkgrnd a, .lasso-v2 th.clsLightGreenBkgrnd a{
  color:#fff; text-decoration:underline; font-weight:700; font-size:13.5px;
}

/* A colored_label pill inside a cell that already carries the SAME bg-* fill
   doubles the colour: a pale chip floating on a saturated cell, and Yes/No end
   up with two different backgrounds each. The cell wins — the pill drops its own
   fill and just supplies big, bold, legible text on it. */
.lasso-v2 td.bg-success .clsColoredLabel > span,
.lasso-v2 td.bg-danger .clsColoredLabel > span,
.lasso-v2 td.bg-primary .clsColoredLabel > span,
.lasso-v2 td.bg-warning .clsColoredLabel > span,
.lasso-v2 td.bg-info .clsColoredLabel > span,
.lasso-v2 td.bg-secondary .clsColoredLabel > span,
.lasso-v2 td.bg-dark .clsColoredLabel > span{
  background:transparent!important; color:#fff!important;
  font-size:13.5px; padding:6px 14px!important;
}

/* app.css numbered board swatches — same story: paired with .text-white on the
   negative-value cells of the HNC boards. */
.lasso-v2 .wb1{ background-color:#4472c4; }
.lasso-v2 .wb2{ background-color:#00b0f0; }
.lasso-v2 .wb3{ background-color:#333f50; }
.lasso-v2 .wb4{ background-color:#ff0000; }
.lasso-v2 .wb5{ background-color:#83766e; }
.lasso-v2 .wb6{ background-color:#782736; }
.lasso-v2 .wb7{ background-color:#5a6f8c; }

/* Same helpers again, one notch more specific, for cells that live in a <thead>.
   `.lasso-v2 .table thead th` (the v2 column-header treatment: uppercase, muted,
   light fill) outranks a bare `.lassobigBoardHeading`, so a report table whose
   TITLE row sits inside thead — which is how ele_table_theme2 and
   ele_table_dashboard build them — lost its filled title bar and came out as pale
   grey column-header text. These restore the legacy look, and reset the
   column-header typography that has no business on a title bar. */
.lasso-v2 .table thead th.lassobigBoardHeading{
  background-color:#58728D; color:#fff;
  text-transform:none; letter-spacing:normal; font-size:13px;
  /* `.lasso-v2 .table th` left-aligns every cell, which outranks the `.text-center`
     the KPI tiles carry — a title bar centres. */
  text-align:center;
}
.lasso-v2 .table thead th.bg-dark{ background-color:#343a40; color:#fff; }
.lasso-v2 .table thead th.bg-success{ background-color:#28a745; color:#fff; }
.lasso-v2 .table thead th.bg-danger{ background-color:#dc3545; color:#fff; }
.lasso-v2 .table thead th.bg-primary{ background-color:#007bff; color:#fff; }
.lasso-v2 .table thead th.clsBlueBkgrnd{ background-color:#3b81ba; color:#fff; }
.lasso-v2 .table thead th.wb1{ background-color:#4472c4; }
.lasso-v2 .table thead th.wb3{ background-color:#333f50; }
.lasso-v2 .table thead th.wb4{ background-color:#ff0000; }

/* `table-bordered` is an explicit request for grid lines. The v2 table treatment
   is borderless with row separators, which reads fine for a list but drops the
   structure out of the dense report boards that ask for borders in markup. */
.lasso-v2 .table-bordered th,
.lasso-v2 .table-bordered td{ border:1px solid var(--line); }

/* ── RECORD WORKBENCH (lv2-*) ─────────────────────────────────────────────────
   Shared shell for single-record admin screens that carry more fields than fit
   above the fold: a pinned context header (identity + fact chips + primary
   actions), then tabbed panes over ONE form. First used by
   templates/HncCallRecordings/form.php. Panes toggle `display` only — every
   control stays in the DOM so a single Save still posts the whole entity. */
.lasso-v2 .lv2-ctx{ background:#fff; border:1px solid var(--line); border-radius:16px; box-shadow:var(--card-shadow); overflow:hidden; }
.lasso-v2 .lv2-ctx-top{ display:flex; gap:18px; align-items:flex-start; padding:16px 20px 14px; }
.lasso-v2 .lv2-ctx-id h1{ font-size:21px; line-height:1.2; margin:0; }
.lasso-v2 .lv2-ctx-id .lv2-sid{ font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11.5px; color:var(--muted); margin-top:3px; }
.lasso-v2 .lv2-ctx-actions{ margin-left:auto; display:flex; gap:8px; align-items:center; flex:0 0 auto; }

.lasso-v2 .lv2-chips{ display:flex; flex-wrap:wrap; gap:7px; padding:0 20px 14px; }
.lasso-v2 .lv2-chip{ display:inline-flex; align-items:center; gap:7px; background:#F7F9FA; border:1px solid var(--line); border-radius:999px; padding:5px 12px; font-size:12.5px; }
.lasso-v2 .lv2-chip .k{ color:var(--muted); font-weight:600; font-size:11px; text-transform:uppercase; letter-spacing:.05em; }
.lasso-v2 .lv2-chip .v{ color:var(--ink); font-weight:600; }
.lasso-v2 .lv2-chip.state{ border-width:1.5px; font-weight:600; }
.lasso-v2 .lv2-chip.state.warn{ background:#FFF6E8; border-color:#F3D9A8; color:#8A6114; }
.lasso-v2 .lv2-chip.state.ok{ background:#EAF7F0; border-color:#B8E2CA; color:#146C3D; }
.lasso-v2 .lv2-chip.state.no{ background:#FDEDEC; border-color:#F5C6C2; color:#96271E; }

.lasso-v2 .lv2-audio{ display:flex; align-items:center; gap:14px; padding:8px 20px; border-top:1px solid var(--line); background:#FBFCFD; }
.lasso-v2 .lv2-audio audio{ flex:1; height:38px; }
.lasso-v2 .lv2-audio .lv2-audio-meta{ font-size:12px; color:var(--muted); white-space:nowrap; }

.lasso-v2 .lv2-tabs{ display:flex; gap:4px; padding:0 12px; background:#fff; margin-top:16px;
  border:1px solid var(--line); border-radius:16px 16px 0 0; overflow-x:auto; }
.lasso-v2 .lv2-tab{ appearance:none; background:transparent; border:0; border-bottom:3px solid transparent;
  padding:11px 18px 9px; font:600 13.5px/1 'Inter',sans-serif; color:var(--muted); cursor:pointer;
  display:inline-flex; align-items:center; gap:8px; white-space:nowrap; }
.lasso-v2 .lv2-tab:hover{ color:var(--ink); }
.lasso-v2 .lv2-tab[aria-selected="true"]{ color:var(--brand-red); border-bottom-color:var(--brand-red); }
.lasso-v2 .lv2-tab .lv2-dot{ width:7px; height:7px; border-radius:50%; background:var(--amber); display:none; }
.lasso-v2 .lv2-tab.is-dirty .lv2-dot{ display:inline-block; }
.lasso-v2 .lv2-tab .lv2-count{ background:#EEF1F4; color:var(--muted); border-radius:999px; padding:2px 7px; font-size:11px; font-weight:700; }

.lasso-v2 .lv2-panels{ background:#fff; border:1px solid var(--line); border-top:0; border-radius:0 0 16px 16px;
  box-shadow:var(--card-shadow); padding:16px; }
.lasso-v2 .lv2-panel{ display:none; }
.lasso-v2 .lv2-panel.is-active{ display:block; }
/* panes are <section> for semantics; strip the generic `.lasso-v2 section` card
   treatment so they don't draw a second frame inside .lv2-panels */
.lasso-v2 .lv2-panels > section.lv2-panel{ background:none; border:0; border-radius:0; box-shadow:none; padding:0; margin:0; }

/* read-only summary / transcript panes */
.lasso-v2 .lv2-readpane h3{ font:700 13px/1 'Inter',sans-serif; text-transform:uppercase; letter-spacing:.07em;
  color:var(--muted); margin:0 0 8px; display:flex; align-items:center; gap:8px; }
.lasso-v2 .lv2-readpane h3 .lv2-spacer{ margin-left:auto; display:inline-flex; align-items:center; gap:12px;
  font-weight:600; font-size:12px; text-transform:none; letter-spacing:0; }
.lasso-v2 .lv2-readpane .lv2-body{ border:1.5px solid var(--line); border-radius:12px; background:#FAFBFC; padding:14px;
  height:140px; overflow:auto; font-size:13.5px; line-height:1.65; white-space:pre-wrap; color:#3A4046; }
.lasso-v2 .lv2-readpane .lv2-body.is-empty{ display:flex; align-items:center; justify-content:center; color:#9AA3AD; font-style:italic; white-space:normal; }

.lasso-v2 .lv2-decide{ border:1.5px solid var(--line); border-radius:12px; padding:16px; background:#FCFDFD; }
.lasso-v2 .lv2-decide .input:last-child{ margin-bottom:0; }

/* the global `.form-group{display:flex}` shim collapses a stacked label onto its
   control, so radio groups that want a label ABOVE carry .lv2-fld instead */
.lasso-v2 .lv2-fld{ margin-bottom:14px; }
.lasso-v2 .lv2-fld > label{ display:block; font-weight:600; font-size:12.5px; color:var(--ink); margin-bottom:6px; }

/* section rule shared by every pane */
.lasso-v2 .lv2-sec{ font:700 11px/1 'Inter',sans-serif; letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
  margin:0 0 12px; padding-bottom:8px; border-bottom:1px solid var(--line); }
.lasso-v2 .lv2-sec.mt{ margin-top:24px; }

/* facts table (label/value pairs, not a data grid) */
.lasso-v2 .lv2-facts{ width:100%; border-collapse:collapse; font-size:13.5px; }
.lasso-v2 .lv2-facts th{ text-align:left; font-weight:600; color:var(--muted); padding:9px 12px; width:210px; vertical-align:top; font-size:12.5px; }
.lasso-v2 .lv2-facts td{ padding:9px 12px; color:var(--ink); }
.lasso-v2 .lv2-facts tr:nth-child(odd){ background:#FAFBFC; }
.lasso-v2 .lv2-facts tr{ border-bottom:1px solid #F0F2F4; }
.lasso-v2 .lv2-mono{ font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; }

.lasso-v2 .lv2-danger{ border:1.5px solid #F5C6C2; background:#FEF7F6; border-radius:12px; padding:14px 16px;
  margin-top:22px; display:flex; align-items:center; gap:14px; }
.lasso-v2 .lv2-danger .t{ font-weight:700; color:#96271E; font-size:13px; }
.lasso-v2 .lv2-danger .d{ font-size:12.5px; color:#8A5F5A; }
.lasso-v2 .lv2-danger .lv2-danger-acts{ margin-left:auto; display:flex; gap:8px; }

.lasso-v2 .lv2-savebar{ position:sticky; bottom:0; margin-top:12px; background:rgba(255,255,255,.94);
  backdrop-filter:blur(6px); border:1px solid var(--line); border-radius:14px;
  box-shadow:0 -2px 14px rgba(20,25,35,.07); padding:9px 18px; display:flex; align-items:center; gap:14px; z-index:5; }
.lasso-v2 .lv2-savebar .lv2-status{ font-size:12.5px; color:var(--muted); }
.lasso-v2 .lv2-savebar .lv2-savebar-right{ margin-left:auto; display:flex; gap:8px; }

/* Review pane, L-shaped: the decision card owns the full-height left column;
   the two reference columns sit across the top; the read-only panes fill the
   space beneath them. That keeps every editable field on the first screen and
   still leaves the panes a usable reading height. */
.lasso-v2 .lv2-review{ display:grid; gap:20px; align-items:start;
  grid-template-columns:340px minmax(0,1fr) minmax(0,1fr);
  grid-template-rows:auto minmax(0,1fr); }
.lasso-v2 .lv2-review > .lv2-decide{ grid-column:1; grid-row:1 / -1; }
.lasso-v2 .lv2-review > .lv2-reads{ grid-column:2 / -1; align-self:stretch; min-height:0; }
@media (max-width:1300px){
  .lasso-v2 .lv2-review{ grid-template-columns:340px minmax(0,1fr);
    grid-template-rows:auto auto minmax(0,1fr); }
  .lasso-v2 .lv2-review > .lv2-reads{ grid-column:2; }
}
@media (max-width:1000px){
  .lasso-v2 .lv2-review{ grid-template-columns:1fr; grid-template-rows:none; }
  .lasso-v2 .lv2-review > .lv2-decide,
  .lasso-v2 .lv2-review > .lv2-reads{ grid-column:auto; grid-row:auto; }
}

/* the read-only summary | transcript pair */
.lasso-v2 .lv2-reads{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:20px; align-items:stretch; }
@media (max-width:1000px){ .lasso-v2 .lv2-reads{ grid-template-columns:1fr; } }

/* The record workbench is a dense, one-screen tool. The branding footer and the
   layout's generous gutters add ~170px of nothing and are the difference
   between fitting the viewport and not, so they step aside on this page only.
   !important is required: templates/element/footer.php sets display:flex inline. */
body:has([data-lv2-record]) footer.footer{ display:none !important; }
body:has([data-lv2-record]) main.lv2-main{ padding-top:14px; padding-bottom:10px; }

/* ── expand a read-only pane ────────────────────────────────────────────────
   The summary / transcription boxes are deliberately short so the whole tab
   fits one screen without a page scrollbar. Reading a long transcript is the
   exception, so it gets an explicit expand button rather than permanent
   height: the pane lifts out to a full-screen overlay (Esc or the button
   closes it). Wired in webroot/js/lv2_record_tabs.js. */
.lasso-v2 .lv2-expand{ appearance:none; background:transparent; border:0; padding:2px 5px; cursor:pointer;
  color:var(--muted); font-size:13px; line-height:1; display:inline-flex; align-items:center; }
.lasso-v2 .lv2-expand:hover{ color:var(--brand-red); }

body.lv2-full-open{ overflow:hidden; }
body.lv2-full-open::before{ content:''; position:fixed; inset:0; background:rgba(20,25,35,.45); z-index:1040; }
.lasso-v2 .lv2-readpane.is-full{ position:fixed; inset:32px; z-index:1050; background:#fff;
  border-radius:16px; box-shadow:0 18px 50px rgba(20,25,35,.28); padding:20px 24px;
  display:flex; flex-direction:column; }
.lasso-v2 .lv2-readpane.is-full .lv2-body{ flex:1 1 auto; height:auto; min-height:0; font-size:14.5px; }

/* ============================================================================
   RECORD SUBMENU — the per-order bar on HBU/HNC pages (.lv2-recordnav)
   `nav_hibu_submenu` / `nav_hnc_submenu` are Bootstrap 4 navbars: a dark bar of
   Edit/Report/Stats links plus PREV/NEXT and a jump-to-record search. default.php
   gets that styling free from Bootstrap's CSS; the clean layout loads Bootstrap's
   JS only, so the bar arrived as an unstyled bullet list once these controllers
   moved to lasso_v2. Ported here scoped to .lv2-recordnav — deliberately NOT as
   generic .navbar rules, which would collide with the lz- global nav above.
   The class is additive on both elements, so pages still on default.php are
   untouched.
   ========================================================================= */
.lasso-v2 .lv2-recordnav{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px;
  background:var(--ink); border-radius:10px;
  padding:7px 12px; margin-bottom:16px;
}
.lasso-v2 .lv2-recordnav .navbar-collapse{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px; flex-basis:100%;
}
.lasso-v2 .lv2-recordnav .navbar-nav{
  display:flex; flex-flow:row wrap; align-items:center; gap:2px;
  list-style:none; margin:0; padding:0;
}
.lasso-v2 .lv2-recordnav .navbar-nav.mr-auto{ margin-right:auto; }
.lasso-v2 .lv2-recordnav .nav-item{ list-style:none; margin:0; }
.lasso-v2 .lv2-recordnav .nav-link{
  display:inline-block; padding:5px 9px; border-radius:7px;
  color:rgba(255,255,255,.82); font-size:12.5px; font-weight:600;
  text-decoration:none; white-space:nowrap;
}
.lasso-v2 .lv2-recordnav .nav-link:hover,
.lasso-v2 .lv2-recordnav .nav-link:focus{ background:rgba(255,255,255,.12); color:#fff; }

/* PREV / NEXT and the search submit. The elements give these Bootstrap's
   .btn.btn-sm.btn-outline-* AND .form-control, so they need to read as buttons
   on a dark bar rather than inheriting the light form-control shim. */
.lasso-v2 .lv2-recordnav .btn{
  display:inline-flex; align-items:center; justify-content:center;
  padding:5px 11px; font-size:12px; font-weight:700; line-height:1.4;
  border-radius:7px; border:1px solid rgba(255,255,255,.45);
  background:transparent; color:#fff; text-decoration:none; white-space:nowrap;
  width:auto; height:auto; min-height:0;
}
.lasso-v2 .lv2-recordnav .btn:hover{ background:rgba(255,255,255,.16); color:#fff; }
.lasso-v2 .lv2-recordnav .btn.disabled,
.lasso-v2 .lv2-recordnav .btn[disabled]{ opacity:.4; pointer-events:none; }
.lasso-v2 .lv2-recordnav .btn-outline-success{ border-color:rgba(120,220,150,.6); }

/* Jump-to-record search: keep the input light so typed text stays readable.
   `width:auto`/`flex:0 0 auto` re-assert this bar's sizing against the generic
   `.input-group` shim above, which is full-width by Bootstrap's definition and
   would otherwise stretch the search box across the nav. */
.lasso-v2 .lv2-recordnav .input-group{ display:flex; align-items:center; gap:5px; width:auto; flex-wrap:nowrap; }
.lasso-v2 .lv2-recordnav .input-group > .form-control{ flex:0 0 auto; }
.lasso-v2 .lv2-recordnav .form-control[type="search"],
.lasso-v2 .lv2-recordnav input[type="search"]{
  width:110px; padding:5px 9px; font-size:12.5px; line-height:1.4;
  border:1px solid rgba(255,255,255,.35); border-radius:7px;
  background:#fff; color:var(--ink); height:auto; min-height:0;
}
.lasso-v2 .lv2-recordnav form{ margin:0; }

/* Mobile toggle — .collapse:not(.show) in lasso-v2-layout.css already hides the
   panel, so the button only needs to look like a button. */
.lasso-v2 .lv2-recordnav .navbar-toggler{
  display:none; padding:4px 8px; background:transparent; cursor:pointer;
  border:1px solid rgba(255,255,255,.45); border-radius:7px;
}
.lasso-v2 .lv2-recordnav .navbar-toggler-icon{
  display:block; width:18px; height:2px; background:#fff; position:relative;
}
.lasso-v2 .lv2-recordnav .navbar-toggler-icon::before,
.lasso-v2 .lv2-recordnav .navbar-toggler-icon::after{
  content:''; position:absolute; left:0; width:18px; height:2px; background:#fff;
}
.lasso-v2 .lv2-recordnav .navbar-toggler-icon::before{ top:-5px; }
.lasso-v2 .lv2-recordnav .navbar-toggler-icon::after{ top:5px; }
/* Each bar carries its own Bootstrap expand breakpoint — HIBU is -lg (992px),
   HNC is -xl (1200px) — so honour both rather than picking one and leaving the
   other with a hidden panel and no visible toggle. */
@media (max-width:991.98px){
  .lasso-v2 .lv2-recordnav.navbar-expand-lg .navbar-toggler{ display:inline-flex; }
}
@media (min-width:992px){
  .lasso-v2 .lv2-recordnav.navbar-expand-lg .navbar-collapse.collapse:not(.show){ display:flex; }
}
@media (max-width:1199.98px){
  .lasso-v2 .lv2-recordnav.navbar-expand-xl .navbar-toggler{ display:inline-flex; }
}
@media (min-width:1200px){
  .lasso-v2 .lv2-recordnav.navbar-expand-xl .navbar-collapse.collapse:not(.show){ display:flex; }
}

/* ── Legacy float + spacing helpers (app.css / listings.css parity) ───────────
   Bootstrap 3-era helpers that never left the admin templates: `pull-right`
   appears in 305 of them, `otherDiv` in 46, `paddingB20` in 7. They came from
   app.css and listings.css, neither of which the clean layout loads, so a
   converted page lost the float entirely — right-aligned action links and
   totals dropped inline into the text flow, and `clearfix` stopped closing the
   float it was there to close. The HBU order-edit page shows all three.
   Ported verbatim rather than modernised: these sit in legacy markup that
   expects floats, and swapping them for flex would move the elements.
   `otherDiv` is deliberately absent — it has no definition in any stylesheet,
   so it is a JS/selector hook, not a style. */
.lasso-v2 .pull-right{ float:right !important; }
.lasso-v2 .pull-left{ float:left !important; }
.lasso-v2 .clearfix{ clear:both; }
/* …but `clear` is inert inside a flex container, and `.lasso-v2 .row` is one.
   The legacy boards break their 12-column runs with a bare
   `<div class="clearfix"></div>` between groups — float-era markup where that
   div ended the line. Under the flex row it became an ordinary flex item:
   zero width, but still separated from its neighbours by the row's 12px gap.
   Twelve columns plus that stolen gap no longer fit on one line, so the LAST
   tile of every run wrapped, and each wrap cascaded into the next group. On
   the HBU big board that pushed Orders Fulfilled out of the second row and
   into the third, where it stole the space Cost Analytics needed — which in
   turn left the flexible `col-lg-4` (Profile Views) as the only growing item
   on its line, at 49% instead of a third.
   Restoring the line-break semantics fixes the whole cascade: the run either
   side of the break gets a full 12 columns to itself again. Empty breaks are
   collapsed back to a single gap so the boards do not gain 12px per group. */
.lasso-v2 .row > .clearfix{ flex:0 0 100%; max-width:100%; }
.lasso-v2 .row > .clearfix:empty{ height:0; margin-top:-6px; margin-bottom:-6px; }
/* A bare <hr> dropped straight into a row is the same story with a visible
   tell: as a flex item it shrinks to its own two-pixel width, so instead of a
   rule across the form the invoice pages showed a stray dot hanging between
   the last field and the buttons. */
.lasso-v2 .row > hr{
  flex:0 0 100%; max-width:100%;
  border:0; border-top:1px solid var(--line); margin:14px 0;
}
.lasso-v2 .paddingB20{ padding-bottom:20px; }

/* Invoice form — "Publish Secondary Recipient List?". A lone checkbox at the
   foot of a long form is easy to miss at the default 13px/13px, so both the
   box and its label are scaled up a step. The nesting label puts the input
   inside the label, hence the flex centring: without it the box sits on the
   text baseline and looks knocked out of line once it is bigger. */
.lasso-v2 .publish-secondary-toggle .checkbox label{
  display:inline-flex; align-items:center; gap:9px;
  font-size:15px; font-weight:600; color:var(--text); margin:0; cursor:pointer;
}
.lasso-v2 .publish-secondary-toggle input[type="checkbox"]{
  width:19px; height:19px; margin:0; flex:0 0 auto; accent-color:var(--blue); cursor:pointer;
}

/* ============================================================================
   WELCOME DASHBOARD — the three big-board buttons + the financial snapshot row
   `.clsWelcomeButton` was defined only in app.css (white text, full width, no
   border), which the clean layout does not load — so the labels fell back to
   the theme's link colour and read as dark text on a dark fill. `bg-success`
   made it worse: only the td/th/tr forms were ported, so the LSO Invoices
   anchor got no fill at all. Restyled here as real v2 buttons rather than a
   verbatim port, and pulled onto the token palette so the row sits with the
   rest of the page instead of using three arbitrary legacy hex values.
   ========================================================================= */
/* No gap override here. The column widths are calc()'d against the theme's 12px
   .row gap, so widening it to 14px made three col-sm-4 buttons overflow their
   row and wrap onto a second line. */
.lasso-v2 .clsWelcomeButtonParentDiv{ align-items:stretch; }
.lasso-v2 .clsWelcomeButton{
  display:flex; align-items:center; justify-content:center;
  /* nowrap so the count pill stays on the label's line rather than dropping
     underneath it and doubling the button's height */
  flex-wrap:nowrap; gap:0;
  width:100%; min-height:40px; padding:9px 14px; border:0;
  border-radius:9px; font-size:13.5px; font-weight:700; letter-spacing:.01em;
  color:#fff !important; text-decoration:none; text-align:center;
  transition:transform .12s ease, box-shadow .12s ease, background-color .12s ease;
}
.lasso-v2 .clsWelcomeButton span{ color:#fff !important; white-space:nowrap; }
.lasso-v2 .clsWelcomeButton:hover{
  color:#fff !important; text-decoration:none; transform:translateY(-1px);
}
/* One hue per destination so the three stay tellable apart at a glance, all
   drawn from the token palette. The shadow is what gives them the pop they
   were missing — a flat fill on a flat page reads as a label, not a control. */
.lasso-v2 .clsWelcomeButton.wb1{ background:var(--blue); box-shadow:0 4px 12px rgba(47,111,214,.26); }
.lasso-v2 .clsWelcomeButton.wb1:hover{ background:#2559B4; box-shadow:0 6px 16px rgba(47,111,214,.34); }
.lasso-v2 .clsWelcomeButton.wb7{ background:var(--ink); box-shadow:0 4px 12px rgba(34,38,43,.24); }
.lasso-v2 .clsWelcomeButton.wb7:hover{ background:#101317; box-shadow:0 6px 16px rgba(34,38,43,.32); }
.lasso-v2 .clsWelcomeButton.bg-success{ background:var(--green) !important; box-shadow:0 4px 12px rgba(31,157,87,.26); }
.lasso-v2 .clsWelcomeButton.bg-success:hover{ background:#177A43 !important; box-shadow:0 6px 16px rgba(31,157,87,.34); }

/* ── Financial snapshot row ──────────────────────────────────────────────────
   Five equal cells: four metric tables and the donut. `.col` alone is
   `flex:1 1 0%`, which never wraps — on a phone that squeezed five tables into
   the viewport width and they overlapped. A real basis lets them wrap. */
.lasso-v2 .fin-snapshot-row{ align-items:stretch; }
.lasso-v2 .fin-snapshot-row > .col{ flex:1 1 210px; min-width:210px; }
@media (max-width:575.98px){
  .lasso-v2 .fin-snapshot-row > .col{ flex:1 1 100%; min-width:0; }
}
/* The donut sat in a bare column while its four neighbours were bordered
   tables with a heading bar — it read as a hole in the row. Give it the same
   frame, header and body so the five cells match. */
.lasso-v2 .fin-snapshot-chart{
  border:1px solid #dee2e6; border-collapse:collapse; width:100%; height:100%;
}
.lasso-v2 .fin-snapshot-chart > thead > tr > th{
  border:1px solid #dee2e6; padding:8px; text-align:left;
}
.lasso-v2 .fin-snapshot-chart > tbody > tr > td{
  border:1px solid #dee2e6; padding:6px; background:#fff; vertical-align:middle;
}

/* ── Unread-lead links on the welcome dashboard ──────────────────────────────
   Same button treatment as the big-board row above, plus a count pill. Given a
   translucent white fill rather than its own colour so it reads as part of the
   button at any of the three hues. */
.lasso-v2 .lead-count{
  display:inline-block; min-width:20px; margin-left:8px; padding:1px 7px;
  border-radius:999px; background:rgba(255,255,255,.24); color:#fff;
  font-size:11.5px; font-weight:800; text-align:center; vertical-align:middle;
}

/* ══════════════════════════════════════════════════════════════════════════
   CUSTOMER PORTAL PAGES
   ══════════════════════════════════════════════════════════════════════════
   choose-platform-package, checkout-overview, setup-complete and expert-calls
   kept their look in webroot/css/portal.css, which only the legacy `default`
   layout loads. They were outside the allow-list in
   CustomersController::beforeRender(), so they stayed on that layout and kept
   their styling. 65b296b59 made lasso_v2 the default layout for every page and
   d909fef38 deleted the allow-list, which moved them onto a layout that
   deliberately loads neither portal.css nor Bootstrap — and they have rendered
   unstyled since.

   These rules RESTORE the design those pages already had. They are portal.css's
   values, not a reinterpretation in the v2 palette: the gradient hero, the
   #3b81ba primary blue that reset-bootstrap-colors.css applied globally on the
   old layout, and the same spacing scale. Scoped to the four page wrappers so
   the blue stops at their edges and the rest of the v2 app keeps brand red.

   Where a rule has no portal.css counterpart it is because lasso_v2 drops a
   Bootstrap base these pages assumed — .card-header{ background:none } kills
   the package card's colour bar, .btn-outline-light is never defined, and the
   grid utilities are shims rather than Bootstrap proper.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Shared dash-* components ────────────────────────────────────────────────
   Hero, setup stepper and the "what happens next" grid for the pre-launch
   campaign dashboard. These were written for the v2 look inside
   templates/element/portal/campaign_dashboard_checklist.php and lived in that
   element's <style> block; they move here unchanged now that the four pages
   below share the same class names and need the definitions to be one thing. */
.lasso-v2 .dash-hero{ padding:0; border:1px solid var(--line); border-left:4px solid var(--brand-red); border-radius:16px; box-shadow:var(--card-shadow); }
.lasso-v2 .dash-hero-body{ padding:22px 26px; }
.lasso-v2 .dash-hero h3{ font-family:'Montserrat','Inter',sans-serif; font-weight:800; font-size:20px; color:var(--ink); margin:0 0 6px; }
.lasso-v2 .dash-hero p{ color:var(--muted); font-size:14px; line-height:1.55; margin:0; max-width:640px; }
.lasso-v2 .dash-hero .badge{ display:inline-block; background:#FFF3E0; color:#B4690E; font-size:11px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; padding:4px 10px; border-radius:999px; }
.lasso-v2 .dash-hero-icon{ width:52px; height:52px; border-radius:14px; background:#E2F4F7; color:var(--teal-dark); display:flex; align-items:center; justify-content:center; font-size:22px; margin-bottom:12px; }

/* horizontal stepper */
.lasso-v2 .dash-stepper{ list-style:none; display:flex; margin:0; padding:6px 0 2px; }
.lasso-v2 .dash-step{ position:relative; flex:1; display:flex; flex-direction:column; align-items:center; text-align:center; gap:8px; padding:0 6px; }
.lasso-v2 .dash-step:not(:last-child)::after{ content:""; position:absolute; top:16px; left:50%; width:100%; height:2px; background:var(--line); z-index:0; }
.lasso-v2 .dash-step.is-done:not(:last-child)::after{ background:var(--green); }
.lasso-v2 .dash-step-circle{ position:relative; z-index:1; width:34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:14px; background:#F1F3F5; color:var(--muted); border:2px solid var(--line); }
.lasso-v2 .dash-step.is-done .dash-step-circle{ background:var(--green); color:#fff; border-color:var(--green); }
.lasso-v2 .dash-step.is-current .dash-step-circle{ background:#fff; color:var(--brand-red); border-color:var(--brand-red); box-shadow:0 0 0 4px rgba(232,54,43,.12); }
.lasso-v2 .dash-step-label{ font-size:12.5px; font-weight:600; color:var(--muted); }
.lasso-v2 .dash-step.is-done .dash-step-label,
.lasso-v2 .dash-step.is-current .dash-step-label{ color:var(--ink); }
.lasso-v2 .dash-step-label a{ font-weight:700; }

@media(max-width:720px){
  .lasso-v2 .dash-stepper{ flex-direction:column; align-items:stretch; gap:12px; }
  .lasso-v2 .dash-step{ flex-direction:row; align-items:center; text-align:left; gap:12px; padding:0; }
  .lasso-v2 .dash-step:not(:last-child)::after{ display:none; }
}

/* ── Gradient hero ───────────────────────────────────────────────────────────
   The original .dash-hero from portal.css. The campaign-dashboard checklist was
   deliberately re-skinned to the flat card above during the v2 work, but
   choose-package, setup-complete and expert-calls were designed against this
   one and their markup assumes it — white headings, a translucent badge and
   light buttons all read against the gradient and nothing else. The three
   opt in with .dash-hero-gradient so which page wants which is stated in the
   markup rather than inferred. */
.lasso-v2 .dash-hero-gradient{
  border:0; border-radius:14px; overflow:hidden; position:relative;
  background:linear-gradient(135deg,#5b21b6 0%,#2563eb 55%,#06b6d4 100%);
  color:#fff; box-shadow:none;
}
.lasso-v2 .dash-hero-gradient::before,
.lasso-v2 .dash-hero-gradient::after{
  content:''; position:absolute; border-radius:50%;
  opacity:.12; background:#fff; pointer-events:none;
}
.lasso-v2 .dash-hero-gradient::before{ width:220px; height:220px; top:-80px; right:-60px; }
.lasso-v2 .dash-hero-gradient::after { width:140px; height:140px; bottom:-50px; left:-40px; }
.lasso-v2 .dash-hero-gradient .dash-hero-body{ position:relative; padding:2rem 2rem 2.25rem; }
.lasso-v2 .dash-hero-gradient .dash-hero-icon{
  width:64px; height:64px; border-radius:50%; background:rgba(255,255,255,.18); color:#fff;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:2.4rem; line-height:1; margin-bottom:.75rem;
}
.lasso-v2 .dash-hero-gradient h3{
  font-family:'Montserrat','Inter',sans-serif; font-weight:700; font-size:1.75rem;
  color:#fff; margin:0 0 .35rem; width:100%;
}
.lasso-v2 .dash-hero-gradient p{ color:rgba(255,255,255,.92); font-size:1rem; margin:0 0 1.25rem; width:100%; max-width:none; }
.lasso-v2 .dash-hero-gradient .badge{
  background:rgba(255,255,255,.18); color:#fff; font-weight:500;
  font-size:.85rem; letter-spacing:0; text-transform:none;
  padding:.35rem .8rem; border-radius:999px;
}
.lasso-v2 .dash-hero-gradient .btn-light{
  font-weight:600; padding:.55rem 1.25rem; border-radius:999px;
  background:#f8f9fa; color:#212529; border-color:#f8f9fa;
  box-shadow:0 4px 14px rgba(0,0,0,.15);
}
.lasso-v2 .dash-hero-gradient .btn-light:hover{ background:#e2e6ea; color:#212529; }
/* lasso-v2-layout.css shims .btn-light but never .btn-outline-light, and
   expert-calls puts one on the gradient. */
.lasso-v2 .dash-hero-gradient .btn-outline-light{
  font-weight:600; padding:.55rem 1.25rem; border-radius:999px;
  background:transparent; color:#fff; border:1px solid rgba(255,255,255,.65);
}
.lasso-v2 .dash-hero-gradient .btn-outline-light:hover{ background:#fff; color:#212529; border-color:#fff; }
.lasso-v2 .dash-hero-rocket{ display:inline-block; animation:dashFloat 3.4s ease-in-out infinite; }
@keyframes dashFloat{
  0%,100%{ transform:translateY(0) rotate(-12deg); }
  50%    { transform:translateY(-6px) rotate(-4deg); }
}

/* ── Legacy primary blue ─────────────────────────────────────────────────────
   reset-bootstrap-colors.css set .btn-primary and .bg-primary to #3b81ba for
   the whole legacy layout, so every primary control on these four pages was
   blue. Restored here, and only here — the rest of the v2 app stays brand red.

   !important throughout: lasso-theme.css:330 and :359 set the brand-red fill
   that way, and a same-!important rule of higher specificity is the only thing
   that beats it. */
.lasso-v2 .page-choose-package .btn-primary,
.lasso-v2 .checkout-overview .btn-primary,
.lasso-v2 .setup-complete-page .btn-primary,
.lasso-v2 .page-expert-calls .btn-primary{
  background:#3b81ba!important; border-color:#3b81ba!important; color:#fff!important;
  box-shadow:none;
}
.lasso-v2 .page-choose-package .btn-primary:hover,
.lasso-v2 .checkout-overview .btn-primary:hover,
.lasso-v2 .setup-complete-page .btn-primary:hover,
.lasso-v2 .page-expert-calls .btn-primary:hover{ background:#3270a4!important; border-color:#3270a4!important; color:#fff!important; }
.lasso-v2 .page-choose-package .btn-outline-primary,
.lasso-v2 .checkout-overview .btn-outline-primary,
.lasso-v2 .setup-complete-page .btn-outline-primary,
.lasso-v2 .page-expert-calls .btn-outline-primary{
  background:transparent!important; color:#3b81ba!important; border:1px solid #3b81ba!important;
}
.lasso-v2 .page-choose-package .btn-outline-primary:hover,
.lasso-v2 .checkout-overview .btn-outline-primary:hover,
.lasso-v2 .setup-complete-page .btn-outline-primary:hover,
.lasso-v2 .page-expert-calls .btn-outline-primary:hover{ background:#3b81ba!important; color:#fff!important; border-color:#3b81ba!important; }

/* ── Full-bleed page width ───────────────────────────────────────────────────
   app.css:80 set `.container{ max-width:unset; padding:2em }` on the legacy
   layout, so these pages ran the full width of the window. The v2 theme caps
   .container at 1080px, which is right for a form but leaves the package cards
   and the checkout steps huddled in the middle of a wide screen. Restore the
   full width for the two pages that were laid out for it. */
.lasso-v2 .page-choose-package.container,
.lasso-v2 .checkout-overview.container,
/* The CCR queue is a dense admin table (7 columns) — a 1080px column squeezed
   the business names and left half a wide screen empty. */
.lasso-v2 .page-ccr-index.container{ max-width:none; padding-left:2em; padding-right:2em; }

/* ── /customers/choose-platform-package ──────────────────────────────────── */
.lasso-v2 .page-choose-package{ font-size:1rem; }
.lasso-v2 .page-choose-package .page-title{ font-size:2rem; font-weight:700; color:#222; margin-bottom:.5rem; }
.lasso-v2 .page-choose-package .page-subtitle{ font-size:1.1rem; color:#666; margin-bottom:2rem; }

/* First-run welcome hero. Still tighter than the shared .dash-hero-gradient so
   the plan cards stay reachable, but scaled up as one block — the type steps up
   proportionally from the "Welcome to Lasso" headline down, and the free-trial
   badge is the loudest line because it is the one that answers "what does this
   cost me right now?". Scoped to this page — the hero is shared. */
.lasso-v2 .page-choose-package.py-4{ padding-top:.5rem; padding-bottom:.75rem; }
.lasso-v2 .page-choose-package .dash-hero{ margin-bottom:.9rem; }
.lasso-v2 .page-choose-package .dash-hero-gradient .dash-hero-body{ padding:1rem 1.75rem 1.15rem; }
.lasso-v2 .page-choose-package .dash-hero-gradient .dash-hero-icon{ width:52px; height:52px; font-size:2rem; margin-bottom:.45rem; }
.lasso-v2 .page-choose-package .dash-hero-gradient h3{ font-size:1.7rem; margin-bottom:.4rem; }
.lasso-v2 .page-choose-package .dash-hero-gradient p{ font-size:1.12rem; margin-bottom:.7rem; }
/* Double the previous .78rem and bold it. Sentence case, not uppercase — the
   gradient variant already clears the base badge's text-transform, so at this
   size it reads as a statement instead of shouting. */
.lasso-v2 .page-choose-package .dash-hero-gradient .badge{ font-size:1.56rem; font-weight:700; padding:.45rem 1.1rem; }

/* Billing toggle */
.lasso-v2 .page-choose-package .billing-toggle-wrapper{ margin-bottom:.4rem; }
.lasso-v2 .page-choose-package .billing-toggle{
  display:inline-flex; align-items:center; gap:.75rem;
  background:#f8f9fa; border-radius:50px; padding:.35rem 1.5rem;
  font-size:1.1rem; font-weight:500;
}
.lasso-v2 .page-choose-package .billing-toggle .toggle-switch{ position:relative; width:50px; height:26px; cursor:pointer; flex-shrink:0; }
.lasso-v2 .page-choose-package .billing-toggle .toggle-switch input{ position:absolute; opacity:0; width:0; height:0; }
.lasso-v2 .page-choose-package .billing-toggle .toggle-slider{ position:absolute; inset:0; background-color:#28a745; border-radius:26px; transition:background-color .2s; }
.lasso-v2 .page-choose-package .billing-toggle .toggle-slider::before{
  content:''; position:absolute; height:20px; width:20px; left:3px; bottom:3px;
  background:#fff; border-radius:50%; transition:transform .2s;
}
.lasso-v2 .page-choose-package .billing-toggle .toggle-switch input:checked + .toggle-slider::before{ transform:translateX(24px); }
.lasso-v2 .page-choose-package .billing-toggle .toggle-label{ cursor:pointer; color:#999; transition:color .2s; }
.lasso-v2 .page-choose-package .billing-toggle .toggle-label.active{ color:#333; font-weight:600; }
.lasso-v2 .page-choose-package .annual-savings-badge{
  display:inline-block; background:#28a745; color:#fff;
  font-size:.8rem; font-weight:600; padding:.2rem .6rem; border-radius:20px;
  margin-left:.5rem; vertical-align:middle;
}
/* Sizes to the badge instead of a fixed height. A fixed 1rem clipped it into
   the cards below, and those are position:relative so they painted over it. The
   toggle only flips `visibility`, which still reserves the space, so letting
   this size naturally costs no layout shift. */
.lasso-v2 .page-choose-package .savings-badge-slot{ line-height:1.2; padding-bottom:.15rem; }

/* Cards. The markup carries .align-items-stretch because the v2 .row centres
   its children, which left the shorter cards floating against the tallest. */
.lasso-v2 .page-choose-package .package-card{
  position:relative; /* anchors .selected-indicator */
  border:2px solid #e9ecef; border-radius:12px; overflow:hidden; cursor:pointer;
  transition:all .25s ease;
}
.lasso-v2 .page-choose-package .package-card:hover{ border-color:#007bff; box-shadow:0 8px 25px rgba(0,123,255,.15); transform:translateY(-2px); }
.lasso-v2 .page-choose-package .package-card.selected{ border:3px solid #28a745; box-shadow:0 8px 25px rgba(40,167,69,.2); transform:translateY(-2px); }
/* Beats lasso-v2-layout's `.card-header{ background:none }`, which would
   otherwise leave the header's own .text-white unreadable. */
.lasso-v2 .page-choose-package .package-card .card-header{
  background:#3b81ba; color:#fff; border-bottom:none;
  font-size:1.1rem; font-weight:700; padding:.6rem 1rem; margin-bottom:0; text-align:center;
}
.lasso-v2 .page-choose-package .package-card .card-body{ padding:.7rem 1rem; }
.lasso-v2 .page-choose-package .selected-indicator{
  display:none; position:absolute; top:10px; right:10px; z-index:2;
  width:28px; height:28px; border-radius:50%; background:#28a745; color:#fff;
  font-size:16px; line-height:28px; text-align:center;
}
.lasso-v2 .page-choose-package .package-card.selected .selected-indicator{ display:block; }

/* Pricing */
.lasso-v2 .page-choose-package .price-section{ min-height:0; display:flex; flex-direction:column; justify-content:center; align-items:center; }
.lasso-v2 .page-choose-package .price-amount{ font-size:2rem; font-weight:700; color:#222; line-height:1; }
.lasso-v2 .page-choose-package .price-period{ font-size:.95rem; color:#888; font-weight:400; }
.lasso-v2 .page-choose-package .price-secondary{ font-size:.85rem; color:#999; margin-top:.25rem; }
.lasso-v2 .page-choose-package .price-custom{ font-size:1.5rem; font-weight:700; color:#222; }
.lasso-v2 .page-choose-package .trial-badge{
  display:inline-block; background:#e8f5e9; color:#2e7d32;
  font-size:.8rem; font-weight:600; padding:.2rem .6rem; border-radius:4px; margin-top:.5rem;
}
/* Holds the row height on the custom-price card so its body lines up with the
   priced cards beside it. */
.lasso-v2 .page-choose-package .trial-badge-placeholder{ visibility:hidden; }

/* Limits. Wraps rather than clips: at four columns a card is ~130px wide inside
   its padding and "4 x 60 min /month" alone is wider than that, so pinned to
   one line it broke "Expert calls" mid-phrase and spilled past the card's
   overflow:hidden. */
.lasso-v2 .page-choose-package .package-limits{
  background:#f8f9fa; border-radius:8px; padding:.5rem .85rem; margin:.5rem 0 0; font-size:.9rem;
}
.lasso-v2 .page-choose-package .package-limits .limit-item{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:2px 10px; padding:.25rem 0; }
.lasso-v2 .page-choose-package .package-limits .limit-value{ margin-left:auto; font-weight:600; color:#333; }

/* Shared feature list, left column */
.lasso-v2 .page-choose-package .shared-features-heading{ font-size:1rem; font-weight:600; color:#333; margin-bottom:.75rem; }
.lasso-v2 .page-choose-package .shared-features{ list-style:none; padding:0; margin:0; }
.lasso-v2 .page-choose-package .shared-features .feature-item{ display:block; padding:.4rem 0; font-size:.95rem; color:#555; }
.lasso-v2 .page-choose-package .shared-features .feature-item::before{ content:'\2713'; color:#28a745; font-weight:700; margin-right:.5rem; }

/* Footer */
/* No max-width. portal.css capped this at 600px, which broke one sentence of
   fine print across three lines and stacked it in a narrow column under three
   full-width cards. */
.lasso-v2 .page-choose-package .bottom-note{ font-size:.78rem; color:#888; margin:.35rem 0 .4rem; }
/* From lg up the note starts where the first package card starts, not at the
   page edge — the shared feature list occupies the first column and the note is
   about the cards. The offset is one col-lg-3 plus the row gap, written with the
   same formula lasso-v2-layout.css uses for the column itself so the two cannot
   drift apart. Below lg the cards go full width and the note lines up already. */
@media(min-width:992px){
  .lasso-v2 .page-choose-package .bottom-note{
    margin-left:calc(3/12 * (100% + 12px));
    text-align:left;
  }
}
.lasso-v2 .page-choose-package .btn-continue{ font-size:1.15rem; padding:.7rem 2rem; border-radius:8px; margin-top:0; }
.lasso-v2 .page-choose-package .btn-continue:disabled{ opacity:.65; cursor:not-allowed; }

/* Locked state — the package is paid and cannot be changed. */
.lasso-v2 .page-choose-package.already-selected .package-card{ pointer-events:none; cursor:default; opacity:.85; }
.lasso-v2 .page-choose-package.already-selected .package-card.selected{ opacity:1; }
.lasso-v2 .page-choose-package.already-selected .package-card:hover{ transform:none; box-shadow:none; border-color:#e9ecef; }

@media(max-width:767.98px){
  .lasso-v2 .page-choose-package .page-title{ font-size:1.5rem; }
  .lasso-v2 .page-choose-package .package-card .card-body{ padding:1rem; }
}

/* ── /customers/checkout-overview ────────────────────────────────────────── */
.lasso-v2 .checkout-overview .co-title{ font-size:2rem; font-weight:700; color:#111827; margin-bottom:.5rem; }
.lasso-v2 .checkout-overview .co-subtitle{ font-size:1.1rem; color:#6b7280; max-width:500px; margin:0 auto; }

.lasso-v2 .checkout-overview .co-step-card{
  height:100%; background:#fff; border:2px solid #e5e7eb; border-radius:12px;
  padding:1.5rem; text-align:center; transition:border-color .2s, box-shadow .2s;
}
.lasso-v2 .checkout-overview .co-step-card.co-step-active{ border-color:#2563eb; box-shadow:0 8px 24px rgba(37,99,235,.12); }
.lasso-v2 .checkout-overview .co-step-card.co-step-done{ border-color:#22c55e; background:#f0fdf4; }
.lasso-v2 .checkout-overview .co-step-badge{
  display:inline-block; background:#2563eb; color:#fff;
  font-size:.8rem; font-weight:700; padding:.2rem .75rem; border-radius:20px; margin-bottom:.75rem;
}
.lasso-v2 .checkout-overview .co-step-badge-muted{ background:#9ca3af; }
.lasso-v2 .checkout-overview .co-step-badge-done{ background:#22c55e; }
.lasso-v2 .checkout-overview .co-step-title{ font-size:1.15rem; font-weight:700; color:#111827; margin-bottom:.25rem; }
.lasso-v2 .checkout-overview .co-step-desc{ font-size:.9rem; color:#6b7280; margin-bottom:1rem; }
.lasso-v2 .checkout-overview .co-step-details{ background:#f9fafb; border-radius:8px; padding:1rem; }
.lasso-v2 .checkout-overview .co-step-name{ font-weight:600; color:#374151; margin-bottom:.5rem; }
.lasso-v2 .checkout-overview .co-step-price{ display:flex; align-items:baseline; justify-content:center; gap:2px; }
.lasso-v2 .checkout-overview .co-currency{ font-size:1rem; font-weight:700; color:#111827; }
.lasso-v2 .checkout-overview .co-amount{ font-size:1.8rem; font-weight:800; color:#111827; letter-spacing:.2px; }
.lasso-v2 .checkout-overview .co-cycle{ font-size:.9rem; color:#6b7280; }
.lasso-v2 .checkout-overview .co-trial-badge{
  display:inline-block; background:#e8f5e9; color:#2e7d32;
  font-size:.8rem; font-weight:600; padding:.2rem .6rem; border-radius:4px; margin-top:.5rem;
}
.lasso-v2 .checkout-overview .co-arrow{ width:32px; height:32px; color:#9ca3af; }

.lasso-v2 .checkout-overview .co-total-card{
  max-width:420px; background:#f9fafb; border:1px solid #e5e7eb; border-radius:10px; padding:1rem 1.25rem;
}
.lasso-v2 .checkout-overview .co-total-row{ display:flex; justify-content:space-between; gap:12px; padding:.4rem 0; font-size:.95rem; color:#374151; }
.lasso-v2 .checkout-overview .co-total-row.co-total-done{ color:#6b7280; text-decoration:line-through; }
.lasso-v2 .checkout-overview .co-total-row.co-total-done span:last-child{ text-decoration:none; color:#22c55e; font-weight:600; }
.lasso-v2 .checkout-overview .co-total-note{ font-size:.8rem; color:#6b7280; margin-top:.5rem; }

/* After the .btn-primary block above — .btn-pay carries its own fill. */
.lasso-v2 .checkout-overview .btn-pay,
.lasso-v2 .checkout-overview .btn-primary.btn-pay{
  display:inline-flex; align-items:center; justify-content:center; gap:10px;
  padding:14px 32px; border:none!important; border-radius:10px; font-size:1.1rem; font-weight:800;
  background:linear-gradient(135deg,#2563eb,#7c3aed)!important; color:#fff!important;
  box-shadow:0 12px 24px rgba(37,99,235,.22);
  transition:transform .05s ease, box-shadow .2s ease;
}
.lasso-v2 .checkout-overview .btn-pay:hover,
.lasso-v2 .checkout-overview .btn-primary.btn-pay:hover{
  background:linear-gradient(135deg,#2563eb,#7c3aed)!important; color:#fff!important;
  transform:translateY(-1px); box-shadow:0 16px 28px rgba(37,99,235,.28);
}
.lasso-v2 .checkout-overview .co-reassurance{ font-size:.85rem; color:#6b7280; }

@media(max-width:767.98px){
  .lasso-v2 .checkout-overview .co-title{ font-size:1.5rem; }
  .lasso-v2 .checkout-overview .co-amount{ font-size:1.5rem; }
}

/* ── /customers/setup-complete ───────────────────────────────────────────── */
.lasso-v2 .setup-complete-page .setup-complete-emoji{ font-size:3rem; line-height:1; }
.lasso-v2 .setup-complete-page .dash-hero-gradient h3{ font-size:1.5rem; }

.lasso-v2 .setup-complete-tiles{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:1rem; }
@media(max-width:767px){ .lasso-v2 .setup-complete-tiles{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(max-width:380px){ .lasso-v2 .setup-complete-tiles{ grid-template-columns:1fr; } }
.lasso-v2 .setup-complete-tile{
  background:#fff; border:1px solid #eef2f7; border-radius:12px;
  padding:1rem .75rem 1.1rem; text-align:center; box-shadow:0 1px 2px rgba(0,0,0,.03);
}
.lasso-v2 .setup-complete-tile-icon{ font-size:1.6rem; line-height:1; margin-bottom:.35rem; }
.lasso-v2 .setup-complete-tile.is-done .setup-complete-tile-icon{ color:#22c55e; }
.lasso-v2 .setup-complete-tile.is-progress .setup-complete-tile-icon{ color:#2563eb; animation:setupCompletePulse 2s ease-in-out infinite; }
@keyframes setupCompletePulse{
  0%,100%{ transform:translateY(0); }
  50%    { transform:translateY(-3px); }
}
.lasso-v2 .setup-complete-tile-label{ font-weight:700; color:#111827; font-size:.92rem; margin-bottom:.15rem; }
.lasso-v2 .setup-complete-tile-status{ color:#6b7280; font-size:.82rem; font-weight:500; }
.lasso-v2 .setup-complete-tile.is-progress .setup-complete-tile-status{ color:#2563eb; font-weight:600; }

.lasso-v2 .setup-complete-actions{ display:flex; flex-wrap:wrap; gap:.75rem; justify-content:center; margin-top:.25rem; }
.lasso-v2 .setup-complete-cta{ padding:12px 32px; border-radius:10px; font-weight:700; min-width:220px; }
@media(max-width:480px){ .lasso-v2 .setup-complete-cta{ width:100%; min-width:0; } }

/* "What happens next" grid — setup-complete only. The checklist element uses
   the same class names but was re-skinned to the flat card treatment, so these
   stay scoped to the page rather than sitting with the shared dash-* rules. */
.lasso-v2 .setup-complete-page .dash-next-grid{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:1rem; }
@media(max-width:767px){ .lasso-v2 .setup-complete-page .dash-next-grid{ grid-template-columns:1fr; } }
.lasso-v2 .setup-complete-page .dash-next-item{ background:#f8fafc; border:1px solid #eef2f7; border-radius:10px; padding:1rem 1rem 1.1rem; }
.lasso-v2 .setup-complete-page .dash-next-item .dash-next-icon{
  width:36px; height:36px; border-radius:50%; background:#ede9fe; color:#6d28d9;
  display:inline-flex; align-items:center; justify-content:center;
  margin-bottom:.55rem; font-size:.95rem;
}
.lasso-v2 .setup-complete-page .dash-next-item h6{ margin:0 0 .2rem; font-weight:600; color:#111827; }
.lasso-v2 .setup-complete-page .dash-next-item p{ margin:0; color:#6b7280; font-size:.85rem; }

/* ── /customers/expert-calls ─────────────────────────────────────────────────
   Reuses the setup-complete tiles for the quota row and the gradient hero for
   the request/buy CTA. Only the buy-ahead affordance is page-specific: the
   button stays clickable while the included quota has headroom and just reads
   as not-urgent. */
.lasso-v2 .buy-call-dim{ opacity:.55; }
.lasso-v2 .buy-call-dim:hover,
.lasso-v2 .buy-call-dim:focus{ opacity:1; }

/* ── /businesses/details ─────────────────────────────────────────────────────
   Same regression, one rule deep: the label column wrapped mid-word without
   it. */
.lasso-v2 .info-table th{ white-space:nowrap; }

/* ── /admin/portal-control-panel ─────────────────────────────────────────────
   A switchboard, not a document: the point is to see every portal switch and
   its state without scrolling, so the cards sit in an auto-filling grid and the
   long explanation of each switch lives in its info tooltip. */
.lasso-v2 .page-portal-control.container{ max-width:none; padding-left:2em; padding-right:2em; }

.lasso-v2 .pcp-head{ display:flex; align-items:baseline; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.lasso-v2 .pcp-title{ font-size:1.8rem; font-weight:700; color:#222; margin:0; }
.lasso-v2 .pcp-summary{ font-size:13px; }
.lasso-v2 .pcp-count{ font-weight:700; font-size:16px; color:#3b81ba; }

.lasso-v2 .pcp-flash{
  margin:12px 0 0; padding:0 12px; max-height:0; overflow:hidden; border-radius:6px;
  font-size:13px; line-height:34px; color:#1b5e20; background:#e8f5e9;
  transition:max-height .18s ease, margin .18s ease;
}
.lasso-v2 .pcp-flash.is-visible{ max-height:60px; margin-bottom:4px; }
.lasso-v2 .pcp-flash.is-error{ color:#8a1c1c; background:#fdecea; }

.lasso-v2 .pcp-grid{
  display:grid; gap:16px; margin-top:16px;
  grid-template-columns:repeat(auto-fill, minmax(420px, 1fr));
  /* Cards size to their own content — without this a short card is stretched to
     match the tallest in its row, which on this page is the long ungated list. */
  align-items:start;
}

.lasso-v2 .pcp-card{ border:1px solid #e3e7ea; border-radius:8px; background:#fff; padding:14px 16px 6px; }
.lasso-v2 .pcp-card-muted{ background:#fafbfc; }
.lasso-v2 .pcp-card-title{
  font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:#6b7780; margin:0 0 10px;
}

.lasso-v2 .pcp-row{
  display:flex; align-items:center; gap:12px;
  padding:9px 0; border-top:1px solid #f0f2f4;
}
.lasso-v2 .pcp-card .pcp-row:first-of-type{ border-top:0; }
.lasso-v2 .pcp-row.is-saving{ opacity:.55; }
.lasso-v2 .pcp-row-caution .pcp-row-label{ color:#8a5a00; }

.lasso-v2 .pcp-row-text{ flex:1 1 auto; min-width:0; }
.lasso-v2 .pcp-row-label{ font-size:13.5px; color:#333; line-height:1.35; }
.lasso-v2 .pcp-row-key code{ font-size:11px; color:#8a949c; background:none; padding:0; }
.lasso-v2 .pcp-info{ color:#9aa4ac; margin-left:5px; cursor:help; }

/* The switch itself — a checkbox with its box hidden, so it keeps keyboard focus
   and form semantics while looking like a slider. */
.lasso-v2 .pcp-switch{ position:relative; flex:0 0 auto; width:40px; height:22px; margin:0; cursor:pointer; }
.lasso-v2 .pcp-switch input{ position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; }
.lasso-v2 .pcp-slider{
  position:absolute; inset:0; border-radius:22px; background:#c8ced3; transition:background .15s ease;
}
.lasso-v2 .pcp-slider::before{
  content:''; position:absolute; top:3px; left:3px; width:16px; height:16px;
  border-radius:50%; background:#fff; transition:transform .15s ease;
}
.lasso-v2 .pcp-switch input:checked + .pcp-slider{ background:#3b81ba; }
.lasso-v2 .pcp-switch input:checked + .pcp-slider::before{ transform:translateX(18px); }
.lasso-v2 .pcp-switch input:focus-visible + .pcp-slider{ outline:2px solid #3b81ba; outline-offset:2px; }
.lasso-v2 .pcp-switch input:disabled + .pcp-slider{ cursor:progress; }

.lasso-v2 .pcp-state{ flex:0 0 28px; font-size:11px; font-weight:700; color:#9aa4ac; text-align:right; }
.lasso-v2 .pcp-state.is-on{ color:#3b81ba; }

.lasso-v2 .pcp-ungated{ list-style:none; margin:0; padding:0 0 8px; }
.lasso-v2 .pcp-ungated li{ padding:6px 0; border-top:1px solid #f0f2f4; }
.lasso-v2 .pcp-ungated li:first-child{ border-top:0; }
.lasso-v2 .pcp-ungated-name{ font-size:13px; color:#333; }
.lasso-v2 .pcp-ungated-where{ display:block; font-size:11px; color:#8a949c; background:none; padding:0; }

/* ── /admin/portal-control-panel: going live ─────────────────────────────────
   The page carries two jobs that look alike and are not: a finite ordered
   checklist for taking the portal live, and an open-ended switchboard for
   running it. They are separated visually so nobody reads the second as the
   first — a tinted, bordered panel for go-live, plain cards below it. */
.lasso-v2 .pcp-golive{
  margin-top:16px; border:1px solid #cfdcea; border-left:4px solid #3b81ba;
  border-radius:8px; background:#f6f9fc;
}
.lasso-v2 .pcp-golive.is-ready{ border-color:#c3e0c6; border-left-color:#2e7d32; background:#f4faf5; }

.lasso-v2 .pcp-golive-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:20px;
  flex-wrap:wrap; padding:14px 18px 12px; border-bottom:1px solid #e3ebf3;
}
.lasso-v2 .pcp-golive-title{ font-size:1.15rem; font-weight:700; color:#1f2b36; margin:0 0 3px; }
.lasso-v2 .pcp-golive-sub{ font-size:12.5px; color:#5d6b78; margin:0; max-width:70ch; line-height:1.5; }
.lasso-v2 .pcp-golive-score{ flex:0 0 auto; }

.lasso-v2 .pcp-badge{
  display:inline-block; padding:4px 12px; border-radius:12px;
  font-size:12px; font-weight:700; letter-spacing:.02em;
}
.lasso-v2 .pcp-badge.is-ok{ color:#1b5e20; background:#e8f5e9; }
.lasso-v2 .pcp-badge.is-blocked{ color:#8a5a00; background:#fdf3e0; }

/* Payment work on the left, switches on the right: they are done in that order
   and the eye reads them in that order. Collapses to one column when there is
   not room for both. */
.lasso-v2 .pcp-golive-body{
  display:grid; gap:0; grid-template-columns:repeat(auto-fit, minmax(440px, 1fr));
  align-items:start;
}
.lasso-v2 .pcp-stage{ padding:14px 18px 16px; }
.lasso-v2 .pcp-stage + .pcp-stage{ border-left:1px solid #e3ebf3; }

.lasso-v2 .pcp-stage-title{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  font-size:13.5px; font-weight:700; color:#1f2b36; margin:0 0 10px;
}
.lasso-v2 .pcp-stage-num{
  flex:0 0 auto; width:20px; height:20px; border-radius:50%;
  background:#3b81ba; color:#fff; font-size:11px; font-weight:700;
  display:inline-flex; align-items:center; justify-content:center;
}
.lasso-v2 .pcp-stage-note{ font-size:11.5px; font-weight:400; color:#6b7780; flex:1 1 100%; line-height:1.45; }
.lasso-v2 .pcp-stage-note strong{ color:#3b81ba; }

.lasso-v2 .pcp-mode{ font-size:12px; color:#6b7780; margin:0 0 10px; }
.lasso-v2 .pcp-mode-value{ margin-left:6px; padding:2px 8px; border-radius:4px; font-size:11.5px; letter-spacing:.04em; }
.lasso-v2 .pcp-mode-value.is-ok{ color:#1b5e20; background:#e8f5e9; }
.lasso-v2 .pcp-mode-value.is-blocked{ color:#8a1c1c; background:#fdecea; }

.lasso-v2 .pcp-checks{ list-style:none; margin:0; padding:0; }
.lasso-v2 .pcp-check{ display:flex; gap:9px; padding:8px 0; border-top:1px solid #e7edf3; }
.lasso-v2 .pcp-check:first-child{ border-top:0; }
.lasso-v2 .pcp-check-dot{
  flex:0 0 auto; width:8px; height:8px; margin-top:5px; border-radius:50%; background:#c8ced3;
}
.lasso-v2 .pcp-check.is-ok .pcp-check-dot{ background:#2e7d32; }
.lasso-v2 .pcp-check.is-blocked .pcp-check-dot{ background:#c77700; }
.lasso-v2 .pcp-check-text{ min-width:0; }
.lasso-v2 .pcp-check-label{ font-size:13px; color:#333; line-height:1.35; }
.lasso-v2 .pcp-check.is-ok .pcp-check-label{ color:#5d6b78; }
.lasso-v2 .pcp-check-detail{ font-size:11.5px; color:#6b7780; line-height:1.5; margin-top:2px; }
.lasso-v2 .pcp-check-action{ font-size:11.5px; color:#3b6ea5; line-height:1.5; margin-top:3px; }
.lasso-v2 .pcp-check-action::before{ content:'\2192\00a0'; }

/* Go-live switch rows. The number is the order, the "needs On/Off" is the target,
   and the left edge is the answer: green once the switch matches what go-live
   wants — which for test mode means off. */
.lasso-v2 .pcp-steps{ margin:0; }
.lasso-v2 .pcp-step{
  border-top:1px solid #e7edf3; padding-left:8px;
  border-left:3px solid transparent; background:transparent;
}
.lasso-v2 .pcp-step:first-child{ border-top:0; }
.lasso-v2 .pcp-step.is-done{ border-left-color:#2e7d32; }
.lasso-v2 .pcp-step.is-pending{ border-left-color:#e0a53a; }
.lasso-v2 .pcp-step-num{
  flex:0 0 auto; width:18px; font-size:11px; font-weight:700; color:#9aa4ac; text-align:right;
}
.lasso-v2 .pcp-step.is-pending .pcp-step-num{ color:#c77700; }
.lasso-v2 .pcp-step.is-done .pcp-step-num{ color:#2e7d32; }
.lasso-v2 .pcp-row-group{ margin-left:8px; font-size:11px; color:#aab3ba; }
.lasso-v2 .pcp-want{
  flex:0 0 auto; font-size:10.5px; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; color:#9aa4ac; white-space:nowrap;
}
.lasso-v2 .pcp-step.is-pending .pcp-want{ color:#c77700; }

.lasso-v2 .pcp-section-title{
  font-size:12px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:#6b7780; margin:26px 0 2px;
}
.lasso-v2 .pcp-section-sub{ font-size:12.5px; color:#8a949c; margin:0; }
.lasso-v2 .pcp-section-title + .pcp-section-sub + .pcp-grid{ margin-top:12px; }

/* An 'unknown' check is not a failure — it means the paid verification has not been
   run in this mode yet. Neutral, with the prompt in the action line. */
.lasso-v2 .pcp-check.is-unknown .pcp-check-dot{ background:#9aa4ac; }

/* Verify prices sits beside the mode badge: it is the one thing on this stage that
   costs something to ask, so it reads as an action rather than a link. */
.lasso-v2 .pcp-verify{
  margin-left:10px; padding:2px 10px; border:1px solid #cfdcea; border-radius:4px;
  background:#fff; color:#3b6ea5; font-size:11.5px; text-decoration:none;
}
.lasso-v2 .pcp-verify:hover{ background:#eef4fa; color:#2c5a8a; text-decoration:none; }
