/* ============================================================
   ANVUL PLATFORM — Fascia & Ledger, cockpit dialect (was "Ink & Signal").
   fascia-ledger.css is linked FIRST and ships the identity (warm paper/ink
   palette · Bricolage/Hanken/Spline voices · THE CLAUSE / THE SUM / FASCIA
   board / THE WALL / STRUCK-PLATE primitives). THIS sheet loads next and is
   the "final word" on the shared :root token NAMES: it keeps the console's
   OWN structure (near-black chrome rail, dense toolbars, the long-session
   working canvas) while re-pointing --paper/--paper-2/--display/--mono onto
   the warm F&L identity and aligning the terracotta accent to F&L's exact
   hex — so all 7 engine screens + Overview + the mobile bar wear F&L at once.
   THE TERRACOTTA ACCENT keeps the name --signal here (its ~40 consumers across
   this + anvul-screens/dash/launch already read it as terracotta); --terra is
   introduced below as the canonical F&L alias to the SAME value. The hard-hat
   SAFETY-ORANGE is reserved under --hat (mark/favicon/OG only) — it is used on
   NO surface here. Same reconciliation proven live in Anvul HQ.html.
   ============================================================ */
:root {
  /* ink / surfaces — warm F&L paper (was pure white/cool grey), on-brand with
     every client-facing surface; the near-black chrome ink stays as the rail. */
  --ink:        oklch(0.205 0.012 264);   /* near-black chrome */
  --ink-2:      oklch(0.255 0.014 264);
  --ink-3:      oklch(0.315 0.014 264);
  --canvas:     #efece3;                  /* dashboard working canvas — F&L paper-deep */
  --paper:      #f4f2ec;                  /* F&L warm paper (was oklch(1 0 0) pure white) */
  --paper-2:    #efece3;                  /* the quiet zebra — F&L paper-deep */

  /* text */
  --fg:         oklch(0.225 0.012 264);
  --fg-soft:    oklch(0.44 0.012 264);
  --fg-faint:   oklch(0.58 0.010 264);
  --fg-ghost:   oklch(0.70 0.008 264);
  --on-ink:     oklch(0.96 0.004 264);
  --on-ink-soft:oklch(0.74 0.010 264);
  --on-ink-faint:oklch(0.60 0.012 264);

  /* lines */
  --line:       oklch(0.91 0.005 264);
  --line-soft:  oklch(0.945 0.004 264);
  --line-strong:oklch(0.85 0.008 264);
  --line-ink:   oklch(0.33 0.012 264);

  /* THE TERRACOTTA ACCENT — Fascia & Ledger's own terracotta, aligned to the
     homepage/HQ EXACTLY (#c75b39 family), replacing the slightly brighter oklch
     the console shipped (#d56c31) so the console reads pixel-for-pixel F&L. The
     name --signal is retained because ~40 existing consumers (here + anvul-
     screens/dash/launch: eyebrows, nav-current, lead rails, funnel stages, live
     dots, chips, focus rings) already read it as the terracotta accent; re-
     colouring in place keeps them ALL terracotta with zero markup churn. */
  --signal:     #c75b39;                  /* = F&L --terra (was oklch(0.645 0.150 47) ≈ #d56c31) */
  --signal-deep:#a8472b;                  /* accent TEXT on light (F&L --terra-text; AA on paper) */
  --signal-soft:rgba(199,91,57,.10);      /* F&L --terra-tint-ish; the tinted CTA/accent wash */
  --signal-line:rgba(199,91,57,.28);      /* accent hairline/border */
  --signal-glow:rgba(199,91,57,.30);
  /* --signal-ink = the deepened terracotta used on FILLS where white sits on top
     (primary-CTA fill, step-number chips, chart strokes, accent-color). Aligned
     to F&L --terra-deep (#9c4127). AA verified: white on #9c4127 = 6.57:1 (PASS);
     white on plain --terra #c75b39 is only 4.21:1 (FAILS AA) — so a fill under
     white text must be this deepened value, NEVER bare --signal/--terra. */
  --signal-ink: #9c4127;
  /* --terra* — the canonical Fascia & Ledger accent names, introduced into the
     console token set. Aliases to the SAME terracotta as --signal above so new
     F&L-idiom code can speak --terra while the legacy --signal consumers are
     untouched. --terra-deep is the AA-safe fill (white on it = 6.57:1). */
  --terra:      #c75b39;
  --terra-text: #a8472b;
  --terra-deep: #9c4127;
  /* THE HAT — the hard-hat's SAFETY-ORANGE (fascia-ledger.css --signal). Codified
     here so it is reserved to the MARK ALONE (favicon / apple-touch / OG share
     card); it appears on NO console surface. NOTHING should read --hat as an
     accent — accents speak --signal / --terra (terracotta). */
  --hat:        #fc6415;

  /* status */
  --ok:         oklch(0.62 0.135 155);
  /* --ok-ink = the deepened green used on small text/dots/fills against light
     (matches the chart block's #1d7a4d "ok" — darker than --ok ~#2e9d61 so it
     holds AA as 11–13px text). Tokenises the raw green re-typed ~5× there. */
  --ok-ink:     #1d7a4d;
  --ok-soft:    oklch(0.955 0.035 155);
  --ok-line:    oklch(0.82 0.070 155);
  --warn:       oklch(0.70 0.135 70);
  --warn-soft:  oklch(0.962 0.045 80);
  --warn-line:  oklch(0.85 0.080 75);
  --block:      oklch(0.585 0.180 25);
  --block-soft: oklch(0.958 0.030 25);
  --block-line: oklch(0.84 0.090 28);

  /* F&L voices (was Space Grotesk / IBM Plex Mono): the fascia display is
     Bricolage Grotesque (condensed wdth axis, used only at display sizes by the
     shared h1/h2 rules in fascia-ledger.css); the clerk's voice for labels + ALL
     money is Spline Sans Mono. Both are loaded up-front (blocking link in the
     HTML head) so they render immediately with no FOUT. Space Grotesk stays in
     the fallback stack for any legacy chrome that still names --display before
     the F&L h1/h2 rules take over. */
  --display: "Bricolage Grotesque", "Space Grotesk", system-ui, sans-serif;
  --sans:    "Hanken Grotesk", system-ui, -apple-system, sans-serif;
  --mono:    "Spline Sans Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --r: 12px; --r-sm: 8px; --r-lg: 18px; --r-xl: 26px;

  /* Type scale — each rung EQUALS a value already in heavy use across the core
     components, so adopting it is a pure 1:1 swap (no rendered size changes).
     Off-grid one-offs (16/18/19/22/23/28/30/32/44px display sizes) deliberately
     keep their literal values; this scale covers the recurring body/label rungs. */
  --text-xs:   11px;    /* pills, eyebrows, mono micro-labels */
  --text-sm:   13px;    /* small body, .btn-sm, metric label */
  --text-base: 14.5px;  /* .btn, checklist titles */
  --text-md:   15.5px;  /* body copy (matches body font-size) */
  --text-lg:   17px;    /* .h-card-title, feature/loop headings */
  --text-xl:   20px;    /* topbar h1, brand */
  --text-2xl:  24px;    /* recap stat figure */
  /* Spacing — 4/8 grid. Matches the components' on-grid paddings/gaps; off-grid
     values (e.g. .card-pad 22px, .pill 6px/11px) are left literal on purpose. */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px;

  --shadow-sm: 0 1px 2px oklch(0.2 0.02 264 / 0.05), 0 4px 12px oklch(0.2 0.02 264 / 0.05);
  --shadow:    0 2px 6px oklch(0.2 0.02 264 / 0.06), 0 16px 40px oklch(0.2 0.02 264 / 0.10);
  --shadow-lg: 0 8px 24px oklch(0.18 0.02 264 / 0.12), 0 40px 90px oklch(0.18 0.02 264 / 0.18);
  --shadow-ink:0 20px 60px oklch(0.1 0.04 264 / 0.45);
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; background: var(--canvas); color: var(--fg); font-family: var(--sans); font-size: var(--text-md); line-height: 1.5; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }  /* --text-md=15.5px (the body rung) */
a { color: inherit; }
::selection { background: var(--signal-soft); }
.mono { font-family: var(--mono); }
.tnum { font-variant-numeric: tabular-nums; }

/* ---------- shared atoms ---------- */
.eyebrow { font-family: var(--mono); font-size: var(--text-xs); letter-spacing: 0.10em; text-transform: uppercase; color: var(--signal-deep); }  /* --text-xs = 11px */
.pill { display: inline-flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: 0.03em; text-transform: uppercase; padding: 6px 11px; border-radius: 999px; border: 1px solid var(--line-strong); color: var(--fg-soft); background: var(--paper); white-space: nowrap; }  /* --text-xs = 11px; padding 6/11 kept literal (off-grid) */
.pill .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--signal); flex: none; }
.pill.ok { color: var(--ok); border-color: var(--ok-line); background: var(--ok-soft); }
.pill.ok .dot { background: var(--ok); }
.pill.warn { color: oklch(0.50 0.12 70); border-color: var(--warn-line); background: var(--warn-soft); }
.pill.warn .dot { background: var(--warn); }
.pill.block { color: var(--block); border-color: var(--block-line); background: var(--block-soft); }
.pill.block .dot { background: var(--block); }
.pill.sig { color: #a8480f; border-color: var(--signal-line); background: var(--signal-soft); }  /* AA: was var(--signal-deep) = 4.24:1 on signal-soft; deepened to >=4.5 */

/* THE STRUCK PLATE, cockpit dialect: F&L retires the 999px pill for a squared
   plate. The console adopts the plate LOOK (squared 5px corner, signwriter's
   inset rule on the primary) but KEEPS its own compact padding/min-height — so
   a dense toolbar (diary day-grid, order cards, filters) stays the same size
   and never breaks. (F&L's own .btn is 52px min-height + 3px; that full 52px
   plate would blow up a toolbar, so this sheet — loaded after F&L — wins with
   the compact console geometry.) */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 9px; font-family: var(--sans); font-size: var(--text-base); font-weight: 700; border: 0; border-radius: 5px; padding: var(--space-3) var(--space-5); cursor: pointer; white-space: nowrap; position: relative; isolation: isolate; transition: background .15s, transform .12s, box-shadow .15s, border-color .15s, color .15s; text-decoration: none; }  /* --text-base=14.5px, padding=12px 20px; radius squared to the plate (was --r-sm 8px) */
.btn svg { width: 17px; height: 17px; }
.btn:active { transform: translateY(1px); }
/* AA (verified numerically): white on plain --terra #c75b39 = 4.21:1 (FAILS the
   4.5 floor), so the primary FILL stays deepened — now --terra-deep #9c4127 =
   6.57:1 (PASS), aligning the console CTA to F&L's --terra-deep. (Was the raw
   #aa4810 = 5.76:1, also passing; --terra-deep is the F&L-canonical value.)
   The struck plate adds the signwriter's rule inside the edge (F&L's own
   .btn-primary::before) — a squared plate, not a pill. */
.btn-primary { background: var(--terra-deep); color: #fff; box-shadow: 0 8px 22px var(--signal-glow), inset 0 1px 0 rgba(255,255,255,.18); }
.btn-primary::before { content: ""; position: absolute; inset: 3px; border: 1px solid rgba(255,255,255,.26); border-radius: 2px; pointer-events: none; }
.btn-primary:hover { background: #8f3d08; }
/* the signwriter's inset rule is a display-scale device: on the small/dense
   primaries that pack the diary day-grid, order cards + toolbars (.btn-sm,
   min-height:0 grid buttons at 2px padding) the 3px inset would collapse over
   the label, so it stands down there — the compact plate keeps just its fill. */
.btn-sm.btn-primary::before,
.dg-ev .btn-primary::before { display: none; }
.btn-ink { background: var(--ink); color: var(--on-ink); }
.btn-ink:hover { background: var(--ink-2); }
.btn-ghost { background: var(--paper); color: var(--fg); border: 1px solid var(--line-strong); }
.btn-ghost:hover { border-color: var(--fg-ghost); background: var(--paper-2); }
.btn-quiet { background: transparent; color: var(--fg-soft); padding: 10px 14px; }
.btn-quiet:hover { background: var(--paper-2); color: var(--fg); }
.btn-lg { font-size: 16px; padding: 15px 26px; border-radius: var(--r); }
.btn-sm { font-size: var(--text-sm); padding: 8px 13px; gap: 6px; }  /* --text-sm=13px; padding kept literal (13px off-grid) */
.btn-block { width: 100%; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow-sm); }
.card-pad { padding: 22px; }

/* score ring */
.ring { --p: 0; --rc: var(--signal); width: 88px; height: 88px; border-radius: 50%; display: grid; place-items: center; position: relative; flex: none;
  background: conic-gradient(var(--rc) calc(var(--p) * 1%), var(--line-soft) 0); }
.ring::before { content: ""; position: absolute; inset: 7px; border-radius: 50%; background: var(--paper); }
.ring .rv { position: relative; font-family: var(--display); font-weight: 700; font-size: 23px; letter-spacing: -0.02em; }
.ring.sm { width: 60px; height: 60px; } .ring.sm::before { inset: 5px; } .ring.sm .rv { font-size: 16px; }
.ring.ok { --rc: var(--ok); } .ring.warn { --rc: var(--warn); } .ring.block { --rc: var(--block); }

/* segmented control */
.seg { display: inline-flex; padding: 3px; gap: 3px; background: var(--paper-2); border: 1px solid var(--line); border-radius: 999px; max-width: 100%; overflow-x: auto; scrollbar-width: none; }  /* scroll instead of overflowing the page on narrow phones (Requests/Leads tabs) */
.seg::-webkit-scrollbar { display: none; }
.seg button { font-family: var(--sans); font-size: 13px; font-weight: 600; color: var(--fg-soft); background: transparent; border: 0; padding: 8px 16px; border-radius: 999px; cursor: pointer; white-space: nowrap; transition: background .15s, color .15s; }
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--on-ink); }

/* checklist line */
.chk { display: flex; align-items: flex-start; gap: 13px; padding: 15px 0; border-bottom: 1px solid var(--line-soft); }
.chk:last-child { border-bottom: 0; }
.chk-ico { width: 24px; height: 24px; border-radius: 50%; flex: none; display: grid; place-items: center; margin-top: 1px; }
.chk-ico svg { width: 13px; height: 13px; }
.chk.done .chk-ico { background: var(--ok); color: #fff; }
.chk.todo .chk-ico { background: var(--paper); border: 1.5px dashed var(--warn-line); color: var(--warn); }
.chk.blocked .chk-ico { background: var(--block); color: #fff; }
.chk-body { flex: 1; min-width: 0; }
.chk-body h4 { font-family: var(--sans); font-weight: 700; font-size: var(--text-base); margin: 0 0 3px; }  /* --text-base=14.5px */
.chk-body p { font-size: 13px; color: var(--fg-soft); margin: 0; line-height: 1.5; }
.chk-act { flex: none; }

/* fix card (Bob) */
.fixcard { border: 1px solid var(--line); border-left: 3px solid var(--signal); border-radius: var(--r-sm); background: var(--paper); padding: 16px 18px; display: flex; gap: 14px; align-items: flex-start; }
.fixcard.warn { border-left-color: var(--warn); }
.fixcard.block { border-left-color: var(--block); }
.fixcard.ok { border-left-color: var(--ok); }
.bob-badge { width: 30px; height: 30px; border-radius: 8px; flex: none; background: var(--ink); color: var(--signal); display: grid; place-items: center; font-family: var(--mono); font-size: 11px; font-weight: 600; }
.fixcard h4 { font-size: 14px; font-weight: 700; margin: 0 0 4px; display: flex; align-items: center; gap: 8px; }
.fixcard .who { font-family: var(--mono); font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-faint); }
.fixcard p { font-size: 13px; color: var(--fg-soft); margin: 0 0 10px; line-height: 1.5; }
.fixcard .fix-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* inputs */
.field label { display: block; font-size: 12.5px; font-weight: 700; color: var(--fg-soft); margin-bottom: 7px; }
.input { width: 100%; font-family: var(--sans); font-size: 15px; color: var(--fg); background: var(--paper); border: 1.5px solid var(--line-strong); border-radius: var(--r-sm); padding: 12px 14px; transition: border-color .15s, box-shadow .15s; }
.input:focus-visible { outline: none; border-color: var(--signal); box-shadow: 0 0 0 4px var(--signal-soft); }  /* :focus-visible — ring on keyboard, not mouse click (matches skin-mobile.css) */
.input::placeholder { color: var(--fg-ghost); }

/* generic reveal (motion engine compatible) */
.reveal { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1 !important; transform: none !important; } }

/* ============================================================
   APP SPLASH — the branded boot moment (markup in Anvul Platform.html).
   Calm, on-brand (Ink & Signal): the mark rises + breathes, the wordmark
   settles under it, and one indeterminate "signal" sweep reads as work-
   in-progress WITHOUT claiming a percentage (honest: no fake progress).
   The base overlay is inline-styled in the HTML so it paints before this
   stylesheet arrives; these rules add the motion + the graceful exit.
   ============================================================ */
/* ---- THE WALL: bricks fly in from every side, assemble bottom-up into a brick
   wall, and at the final beat the ANVUL wordmark is sprayed on as a stencil mural.
   Barbershop/street character (on-brand for the barbers + salons beachhead), not
   corporate. Pure CSS/SVG — bricks are boxes, mural is text. Transforms + opacity
   only, so it stays smooth on a mid phone. The animation reads well whether it runs
   to completion OR the app fades it out mid-build. ---- */
.app-splash {
  /* honor the safe area so the wall optically sits true on a notched phone */
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  background:
    radial-gradient(130% 90% at 50% 42%, oklch(0.86 0.035 60 / 0.6), transparent 62%),
    var(--paper-warm, #efe9df) !important;
  transition: opacity .42s var(--ease-soft, ease), visibility .42s;
  will-change: opacity;
  overflow: hidden;
}
.app-splash.is-out { opacity: 0; visibility: hidden; pointer-events: none; }
/* the inline no-CSS fallback wordmark: once this stylesheet is live, the real
   scene renders, so hide the plain-text fallback (and its inline drip). */
.app-splash .asp-fallback, .app-splash .asp-drip { display: none !important; }

.app-splash .asp-scene { position: relative; }

/* ---- the wall grid: 8 columns × 5 courses in running bond. Full bricks span 2
   columns, half bricks span 1 — so alternate courses offset by a half like real
   masonry (not a stack-bond tile grid). ---- */
.app-splash .asp-wall {
  position: absolute; inset: 0;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-auto-rows: 1fr;
  gap: clamp(3px, 1.4vw, 6px);
  border-radius: 5px;
  /* a soft cast shadow so the finished wall reads as a solid object on the paper */
  filter: drop-shadow(0 18px 30px oklch(0.36 0.06 45 / 0.18));
}
.app-splash .brick {
  position: relative;
  grid-column: span 2;   /* a full brick = 2 of the 8 columns */
  border-radius: 3px;
  /* warm terracotta / clay brick face, each with a faint top-light + baked edge */
  background:
    linear-gradient(160deg, oklch(0.71 0.115 48) 0%, oklch(0.63 0.130 42) 55%, oklch(0.57 0.120 40) 100%);
  box-shadow:
    inset 0 1.5px 0 oklch(0.82 0.09 60 / 0.55),
    inset 0 -2px 3px oklch(0.42 0.10 40 / 0.45),
    inset 0 0 0 1px oklch(0.5 0.10 40 / 0.25);
  transform: translate(var(--fx, 0), var(--fy, 0)) rotate(var(--fr, 0)) scale(.9);
  opacity: 0;
  animation: brickIn .62s cubic-bezier(.2,.9,.25,1.05) both;
  animation-delay: var(--bd, 0s);
  will-change: transform, opacity;
}
/* half-brick starts/ends of the staggered courses (running bond) = 1 column */
.app-splash .brick.half { grid-column: span 1; }
/* a subtle mortar speckle so bricks don't look like flat plastic */
.app-splash .brick::after {
  content: ""; position: absolute; inset: 0; border-radius: 3px; opacity: .5;
  background:
    radial-gradient(1px 1px at 22% 34%, oklch(0.5 0.08 40 / 0.5), transparent 60%),
    radial-gradient(1px 1px at 68% 62%, oklch(0.82 0.06 60 / 0.5), transparent 60%),
    radial-gradient(1.5px 1.5px at 46% 80%, oklch(0.5 0.08 40 / 0.4), transparent 60%);
}

/* fly-in choreography — bottom course lands first, top course last, so the wall
   visibly "builds up". Directions alternate (left / right / top) for character.
   22 bricks across 5 courses: 1-4 (top), 5-9, 10-13 (middle), 14-18, 19-22 (bottom). */
.app-splash .brick:nth-child(19){ --fx:-120%; --fy: 40%;  --fr:-8deg; --bd:.02s; } /* bottom course — in first */
.app-splash .brick:nth-child(20){ --fx: 130%; --fy: 30%;  --fr: 7deg; --bd:.10s; }
.app-splash .brick:nth-child(21){ --fx:-90%;  --fy: 60%;  --fr:-6deg; --bd:.06s; }
.app-splash .brick:nth-child(22){ --fx: 110%; --fy: 50%;  --fr: 9deg; --bd:.14s; }
.app-splash .brick:nth-child(14){ --fx:-130%; --fy: 20%;  --fr:-7deg; --bd:.20s; } /* 4th course */
.app-splash .brick:nth-child(15){ --fx: 140%; --fy:-20%;  --fr: 8deg; --bd:.28s; }
.app-splash .brick:nth-child(16){ --fx:-100%; --fy:-30%;  --fr:-9deg; --bd:.24s; }
.app-splash .brick:nth-child(17){ --fx: 90%;  --fy:-40%;  --fr: 6deg; --bd:.32s; }
.app-splash .brick:nth-child(18){ --fx: 120%; --fy: 25%;  --fr: 7deg; --bd:.36s; }
.app-splash .brick:nth-child(10){ --fx:-140%; --fy:-10%;  --fr:-6deg; --bd:.42s; } /* middle course */
.app-splash .brick:nth-child(11){ --fx: 0%;   --fy:-150%; --fr: 4deg; --bd:.50s; }
.app-splash .brick:nth-child(12){ --fx: 130%; --fy:-20%;  --fr: 7deg; --bd:.46s; }
.app-splash .brick:nth-child(13){ --fx: 100%; --fy:-60%;  --fr: 8deg; --bd:.54s; }
.app-splash .brick:nth-child(5) { --fx:-110%; --fy:-70%;  --fr:-8deg; --bd:.58s; } /* 2nd course */
.app-splash .brick:nth-child(6) { --fx: 0%;   --fy:-160%; --fr:-5deg; --bd:.66s; }
.app-splash .brick:nth-child(7) { --fx: 120%; --fy:-60%;  --fr: 6deg; --bd:.62s; }
.app-splash .brick:nth-child(8) { --fx: 90%;  --fy:-120%; --fr: 9deg; --bd:.70s; }
.app-splash .brick:nth-child(9) { --fx: 110%; --fy:-90%;  --fr: 5deg; --bd:.74s; }
.app-splash .brick:nth-child(1) { --fx:-90%;  --fy:-130%; --fr:-7deg; --bd:.80s; } /* top course — lands last */
.app-splash .brick:nth-child(2) { --fx: 0%;   --fy:-180%; --fr: 5deg; --bd:.88s; }
.app-splash .brick:nth-child(3) { --fx: 100%; --fy:-120%; --fr: 7deg; --bd:.84s; }
.app-splash .brick:nth-child(4) { --fx: 80%;  --fy:-150%; --fr:-6deg; --bd:.92s; }

/* a dust puff that settles as the last bricks land */
.app-splash .asp-dust {
  position: absolute; inset: -6% -4% -12% -4%; z-index: 3; pointer-events: none;
  border-radius: 50%; opacity: 0;
  background: radial-gradient(60% 40% at 50% 88%, oklch(0.9 0.03 60 / 0.55), transparent 70%);
  animation: dustPuff 1s ease-out .98s both;
}

/* ---- the mural: sprayed on once the wall is up (delay ≈ last brick + settle) ---- */
.app-splash .asp-mural {
  position: absolute; inset: 0; z-index: 4;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(6px, 1.6vw, 12px);
  opacity: 0;
  animation: muralSpray .52s var(--ease-out, cubic-bezier(.22,.8,.28,1)) 1.12s both;
}
.app-splash .asp-mark {
  width: clamp(26px, 8vw, 34px); height: clamp(26px, 8vw, 34px);
  display: grid; place-items: center; color: oklch(0.965 0.02 70);
  /* stencil chip: cream on a knocked-back terracotta plate = spray-through look */
  border-radius: 7px;
  background: oklch(0.5 0.13 40 / 0.28);
  box-shadow: inset 0 0 0 1.5px oklch(0.97 0.02 70 / 0.5);
  filter: drop-shadow(0 2px 4px oklch(0.3 0.08 40 / 0.4));
}
.app-splash .asp-mark svg { width: 68%; height: 68%; }
.app-splash .asp-word {
  font-family: var(--display, "Space Grotesk"), system-ui, sans-serif;
  font-weight: 700; font-size: clamp(42px, 15vw, 64px); line-height: .9;
  letter-spacing: -0.03em;
  /* cream stencil on the brick, with a spray halo + a hard edge for that painted feel */
  color: oklch(0.965 0.02 70);
  text-shadow:
    0 1px 0 oklch(0.4 0.10 40 / 0.5),
    0 0 1px oklch(0.5 0.13 40 / 0.9),
    0 3px 10px oklch(0.35 0.10 40 / 0.55);
  -webkit-text-stroke: 0.5px oklch(0.5 0.13 40 / 0.35);
}
/* the honest indeterminate mark — a terracotta "spray drip" that breathes, never a % */
.app-splash .asp-mural::after {
  content: ""; width: clamp(70px, 22vw, 104px); height: 3px; border-radius: 999px;
  margin-top: clamp(4px, 1.4vw, 10px); overflow: hidden;
  background:
    linear-gradient(90deg, transparent, oklch(0.965 0.02 70 / 0.9), transparent) no-repeat,
    oklch(0.5 0.13 40 / 0.3);
  background-size: 42% 100%, 100% 100%;
  animation: aspSweep 1.5s ease-in-out 1.4s infinite;
}

@keyframes brickIn {
  0%   { opacity: 0; transform: translate(var(--fx,0), var(--fy,0)) rotate(var(--fr,0)) scale(.9); }
  70%  { opacity: 1; }
  85%  { transform: translate(0,0) rotate(0) scale(1.015); }   /* tiny overshoot = it "lands" */
  100% { opacity: 1; transform: translate(0,0) rotate(0) scale(1); }
}
@keyframes dustPuff { 0% { opacity: 0; transform: scale(.7); } 40% { opacity: 1; } 100% { opacity: 0; transform: scale(1.1); } }
@keyframes muralSpray {
  0%   { opacity: 0; transform: scale(1.08); filter: blur(3px); }
  60%  { opacity: 1; filter: blur(0); }
  100% { opacity: 1; transform: scale(1); filter: blur(0); }
}
@keyframes aspSweep { 0% { background-position: -60% 0, 0 0; } 100% { background-position: 160% 0, 0 0; } }
/* reused by the reconnect chip (a slow breath) + its honest sweep (translateX sliver) */
@keyframes aspBreathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }
@keyframes rdSweep { 0% { transform: translateX(-140%); } 100% { transform: translateX(340%); } }

/* ---- prefers-reduced-motion: skip the whole build. Show the FINISHED state
   instantly — a complete brick wall with the ANVUL mural already on it, no motion. ---- */
@media (prefers-reduced-motion: reduce) {
  .app-splash { transition: none; }
  .app-splash .brick, .app-splash .brick.half {
    animation: none; opacity: 1; transform: none;
  }
  .app-splash .asp-mural { animation: none; opacity: 1; transform: none; }
  .app-splash .asp-mural::after { animation: none; width: clamp(70px, 22vw, 104px);
    background-size: 40% 100%, 100% 100%; background-position: 30% 0, 0 0; }
  .app-splash .asp-dust { animation: none; opacity: 0; }
}

/* ---- Reconnect takeover (#rdRetry, built in anvul-app.js) — on-brand, calm.
     Full-viewport paper wash with a centred card carrying the Anvul mark, the
     UNCHANGED honest reassurance, and an indeterminate signal sweep (no %). ---- */
.rd-retry {
  position: fixed; inset: 0; z-index: 90; display: flex; align-items: center; justify-content: center;
  padding: calc(24px + env(safe-area-inset-top)) 24px calc(24px + env(safe-area-inset-bottom));
  background:
    radial-gradient(120% 80% at 50% 30%, oklch(0.645 0.150 47 / 0.05), transparent 60%),
    var(--paper, #f4f2ec);
  animation: anvFade .25s ease both;
}
.rd-retry-card { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0; max-width: 440px; }
/* a single brick chip carrying the mark — cohesive with the boot wall */
.rd-retry-mark { width: 54px; height: 42px; display: grid; place-items: center; margin-bottom: 18px;
  border-radius: 5px; padding: 7px;
  background: linear-gradient(160deg, oklch(0.71 0.115 48) 0%, oklch(0.63 0.130 42) 55%, oklch(0.57 0.120 40) 100%);
  box-shadow: inset 0 1.5px 0 oklch(0.82 0.09 60 / 0.55), inset 0 -2px 3px oklch(0.42 0.10 40 / 0.45),
    inset 0 0 0 1px oklch(0.5 0.10 40 / 0.25), 0 8px 20px oklch(0.36 0.06 45 / 0.2);
  animation: aspBreathe 3.4s ease-in-out infinite; }
.rd-retry-mark img { width: 100%; height: 100%; object-fit: contain; display: block; filter: brightness(0) invert(1) opacity(.92); }
.rd-retry-h { margin: 0 0 8px; font-family: var(--display); font-weight: 700; font-size: 18px; letter-spacing: -0.02em; color: var(--fg); }
.rd-retry-p { margin: 0 0 18px; font-size: 13.5px; line-height: 1.55; color: var(--fg-soft); max-width: 40ch; }
.rd-retry-track { width: 116px; height: 3px; border-radius: 999px; overflow: hidden; background: var(--line); margin-bottom: 14px; }
.rd-retry-track > span { display: block; width: 42%; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--signal), transparent); animation: rdSweep 1.35s ease-in-out infinite; }
.rd-retry-status { margin: 0 0 16px; min-height: 15px; font-family: var(--mono); font-size: 11.5px; color: var(--fg-faint); }
.rd-retry .btn-ghost { min-height: 44px; }
@media (prefers-reduced-motion: reduce) {
  .rd-retry { animation: none; } .rd-retry-mark { animation: none; }
  .rd-retry-track > span { animation: none; width: 40%; }
}

/* ============================================================
   CONCIERGE (Workstream A) — Simple/Advanced view · Requests · Preview
   Additive surface, in the same Ink & Signal language as above. Reuses the
   shared atoms (.card / .pill / .input / .btn / .field) wherever possible.
   ============================================================ */

/* ---- Simple / Advanced view ----
   Default 'simple': only the four concierge nav items (data-simple) show and
   the group eyebrows collapse to a clean flat list. Advanced reveals every
   screen. This hides NAV ONLY — every screen stays deep-linkable, so hiding
   nav never dead-ends. */
#view-app[data-dash-mode='simple'] .nav-item:not([data-simple]) { display: none; }
#view-app[data-dash-mode='simple'] .nav-group .ng-l { display: none; }
#view-app[data-dash-mode='simple'] .nav-group { margin-bottom: 6px; }
/* a group with no simple items leaves no gap (progressive — :has() is in all
   current browsers; without it the group just shows its small margin). */
#view-app[data-dash-mode='simple'] .nav-group:not(:has(.nav-item[data-simple])) { display: none; }

/* the view toggle — a quiet control at the foot of the dark rail */
.nav-mode { display: flex; align-items: center; gap: 9px; width: 100%; margin-top: 4px; padding: 9px 10px;
  border: 1px solid var(--line-ink); border-radius: var(--r-sm); background: transparent; color: var(--on-ink-soft);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600;
  cursor: pointer; transition: background .14s, color .14s, border-color .14s; }
.nav-mode:hover { background: var(--ink-2); color: var(--on-ink); border-color: var(--ink-3); }
.nav-mode:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.nav-mode svg { width: 15px; height: 15px; flex: none; opacity: 0.75; }
.nav-mode .dm-label { flex: 1; text-align: left; }
.nav-mode[aria-pressed='true'] svg { color: var(--signal); opacity: 1; }

/* ---- Requests ("Ask us" concierge intake) ---- */
/* native select dressed as a .input (own chevron; appearance reset) */
select.input { appearance: none; -webkit-appearance: none; cursor: pointer; padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%237b7b85' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px; }
.req-form-foot { display: flex; align-items: center; gap: 14px; margin-top: 16px; flex-wrap: wrap; }
.req-msg { font-size: 13px; }
.req-msg.ok { color: var(--ok-ink); font-weight: 600; }
.req-msg.err { color: var(--block); font-weight: 600; }
.req-list { display: flex; flex-direction: column; gap: 12px; }
.req-card-h { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.req-kind { font-weight: 700; font-size: var(--text-base); color: var(--fg); }  /* --text-base=14.5px */
.req-when { font-family: var(--mono); font-size: 11px; color: var(--fg-faint); }
.req-card .pill { flex: none; }
.req-body { font-size: 14px; color: var(--fg-soft); margin: 12px 0 0; line-height: 1.55; white-space: pre-wrap; }
.req-note { margin-top: 12px; padding: 11px 13px; border-left: 3px solid var(--signal); background: var(--signal-soft);
  border-radius: var(--r-sm); font-size: 13px; color: var(--fg); line-height: 1.5; }
.req-note-l { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--signal-deep); margin-bottom: 4px; }
.req-empty { text-align: center; color: var(--fg-soft); }
.req-empty p { margin: 0; font-size: 14px; line-height: 1.5; }
.req-empty a { color: var(--signal-deep); font-weight: 600; white-space: nowrap; }

/* ---- Request photos ("got a photo of the job?") ---- */
.req-photos { margin-top: 14px; }
.req-thumbs { display: flex; flex-wrap: wrap; gap: 8px; }
.req-thumbs:not(:empty) { margin-bottom: 10px; }
.req-thumb { position: relative; width: 64px; height: 64px; border-radius: var(--r-sm, 8px); overflow: hidden; border: 1px solid var(--line, #e3e3e6); background: var(--paper-2, #f4f4f5); }
.req-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.req-thumb-x { position: absolute; top: 2px; right: 2px; width: 24px; height: 24px; border: 0; border-radius: 50%;
  background: rgba(0,0,0,.62); color: #fff; font-size: 13px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; }
.req-thumb-x:hover { background: rgba(0,0,0,.82); }
.req-photo-add { cursor: pointer; }
.req-card-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.req-card-thumbs img { width: 88px; height: 88px; object-fit: cover; border-radius: var(--r-sm, 8px); border: 1px solid var(--line, #e3e3e6); }

/* ---- Request tabs + video attachments (additive) ---- */
.req-tabpanel { margin-top: 14px; }
.req-add-row { display: flex; flex-wrap: wrap; gap: 8px; }
/* video "chips" in the form: a play icon + the real filename, each removable */
.req-vids { display: flex; flex-direction: column; gap: 8px; }
.req-vids:not(:empty) { margin-bottom: 10px; }
.req-vid { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper-2); font-size: 13px; color: var(--fg); max-width: 360px; }
.req-vid .req-vid-ic { width: 26px; height: 26px; border-radius: 6px; flex: none; display: grid; place-items: center; background: var(--ink); color: var(--on-ink); }
.req-vid .req-vid-ic svg { width: 13px; height: 13px; }
.req-vid .req-vid-n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.req-vid-x { flex: none; width: 24px; height: 24px; border: 0; border-radius: 50%; background: var(--line-soft); color: var(--fg-soft); font-size: 14px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; }
.req-vid-x:hover { background: var(--block-soft); color: var(--block); }
/* videos on the request CARDS (status list) */
.req-card-vids { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.req-card-vids video { width: 240px; max-width: 100%; border-radius: var(--r-sm); border: 1px solid var(--line); background: #000; display: block; }

/* ============================================================
   CONNECT — "you connect your Google listing, we handle the rest"
   Additive, in the same Ink & Signal language. Reuses .card / .chk /
   .pill / .input / .btn / .field / .seo-edu wherever possible.
   ============================================================ */
.cn-connect-row { display: flex; gap: 9px; flex-wrap: wrap; }
.cn-connect-row .input { flex: 1; min-width: 220px; }
.cn-connect-row .btn { flex: 0 0 auto; }
.cn-msg { font-size: 12.5px; line-height: 1.5; }
.cn-msg a { color: var(--signal-deep); font-weight: 600; }
.cn-extras > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; }
.cn-extras > summary::-webkit-details-marker { display: none; }
.cn-extras-sum { font-size: var(--text-base); }  /* --text-base = 14.5px */
.cn-extras .cn-chev { width: 18px; height: 18px; color: var(--fg-soft); margin-left: auto; transition: transform .2s; flex: none; }
.cn-extras[open] .cn-chev { transform: rotate(90deg); }
.cn-extras-body { margin-top: 14px; }

/* Domain handoff = the LIGHTER, secondary "next step" card. Google connect is
   the one primary action; this sits below it as an optional upgrade so the two
   never read as equal-weight CTAs (lighter surface, no lift, smaller heading). */
.cn-next { background: var(--paper-2); box-shadow: none; }
.cn-next .h-card-title { font-size: var(--text-md); }  /* a notch under the Google card's 17px */

/* "Handled for you" — collapsed to ONE reassuring line; expand for the detail.
   Mirrors the .cn-extras disclosure so the two collapsibles read as a pair. */
.cn-handled > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 12px; }
.cn-handled > summary::-webkit-details-marker { display: none; }
.cn-handled-ico { background: var(--ok); color: #fff; }  /* fills the shared .chk-ico circle */
.cn-handled-line { flex: 1; min-width: 0; font-size: var(--text-base); color: var(--fg); line-height: 1.45; }  /* --text-base = 14.5px */
.cn-handled-line b { color: var(--ok-ink); }
.cn-handled-hint { flex: none; font-family: var(--mono); font-size: var(--text-xs); color: var(--fg-faint); white-space: nowrap; }  /* --text-xs = 11px */
.cn-handled .cn-chev { width: 18px; height: 18px; color: var(--fg-soft); transition: transform .2s; flex: none; }
.cn-handled[open] .cn-handled-hint { display: none; }
.cn-handled[open] .cn-chev { transform: rotate(90deg); }
.cn-handled-body { margin-top: 8px; }
@media (max-width: 480px) { .cn-handled-hint { display: none; } }

/* STATE 1 — "WE FOUND IT": the one-tap confirm card. Signal-tinted so it reads as
   the primary path. HONESTY: carries name + address + a confidence-framed prompt
   only — NEVER a rating or review count (those don't exist until truly connected). */
.cn-found { border: 1px solid var(--signal-line); background: var(--signal-soft); border-radius: var(--r); padding: 16px 18px; }
.cn-found-head { margin-bottom: 10px; }
.cn-found-name { font-family: var(--display); font-weight: 600; font-size: var(--text-lg); color: var(--fg); line-height: 1.2; }  /* --text-lg = 17px */
.cn-found-addr { font-size: var(--text-sm); color: var(--fg-soft); margin-top: 3px; }  /* --text-sm = 13px */
.cn-found-prompt { font-size: 13px; color: var(--fg-soft); line-height: 1.5; margin: 10px 0 14px; max-width: 56ch; }
.cn-found-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cn-manual-wrap { margin-top: 16px; }
.cn-manual-wrap[hidden] { display: none; }

/* STATE 2 — honest "no listing yet?" create-guide + the honest skip. Calm,
   secondary surfaces so the manual paste above stays the obvious primary action. */
.cn-create { margin-top: 16px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper-2); }
.cn-create h4 { font-family: var(--sans); font-weight: 700; font-size: var(--text-base); margin: 0 0 5px; }  /* --text-base = 14.5px */
.cn-create p { font-size: 13px; color: var(--fg-soft); line-height: 1.55; margin: 0 0 12px; max-width: 60ch; }
.cn-skip { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 14px; }
.cn-skip .muted { font-size: 12.5px; line-height: 1.5; max-width: 46ch; }
.cn-skip-ico { background: var(--paper); border: 1.5px solid var(--line-strong); color: var(--fg-faint); }  /* neutral, not a "done" tick */

@media (max-width: 640px) { .cn-connect-row .btn { width: 100%; } .cn-found-actions { flex-direction: column; align-items: stretch; } .cn-found-actions .btn { width: 100%; } }

/* GBP SETUP HELPER — the pre-filled "we'll get you on Google" panel that
   replaces the old static create-guide inside the manual connect block. Reuses
   the .dh-* path/step/value atoms + .chk + .field; these .gbpp-* pieces are only
   the wrapper + the pre-fill CONFIRM list (so it reads as a confirm, not a form). */
.gbpp-host { margin-top: 16px; }
.gbpp-wrap { padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper-2); }
.gbpp-head h4 { font-family: var(--sans); font-weight: 700; font-size: var(--text-base); margin: 0 0 5px; }  /* --text-base = 14.5px */
.gbpp-head p { font-size: 13px; color: var(--fg-soft); line-height: 1.55; margin: 0 0 14px; max-width: 62ch; }
.gbpp-confirm { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); padding: 12px 14px; }
.gbpp-confirm-h { font-size: 12.5px; font-weight: 700; color: var(--fg-soft); margin-bottom: 9px; }
.gbpp-list { display: flex; flex-direction: column; gap: 7px; }
.gbpp-row { display: flex; gap: 12px; align-items: baseline; font-size: 13px; line-height: 1.45; }
.gbpp-k { flex: 0 0 116px; color: var(--fg-faint); font-size: 12.5px; }
.gbpp-v { flex: 1; min-width: 0; color: var(--fg); font-weight: 600; overflow-wrap: anywhere; }
.gbpp-wrap .auth-copy { padding: 2px 9px; font-size: 11.5px; vertical-align: 1px; }
@media (max-width: 560px) { .gbpp-row { flex-direction: column; gap: 1px; } .gbpp-k { flex: none; } }

/* ---- Preview ("Your site") ---- */
/* scoped to beat .between (align-items:center) from anvul-screens.css */
.pv-head .pv-head-row { flex-wrap: wrap; align-items: flex-start; }
.pv-host { display: block; font-family: var(--mono); font-size: 12px; color: var(--fg-faint); }
.pv-actions { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.pv-frame-wrap { margin-top: 16px; padding: 0; overflow: hidden; }
.pv-frame { display: block; width: 100%; height: min(72vh, 820px); border: 0; background: var(--paper-2); }
@media (max-width: 640px) { .pv-frame { height: 64vh; } .pv-actions { width: 100%; } }

/* ============================================================
   LEADS INBOX — bespoke, scannable lead cards (additive)
   Reuses .lead-row / .lead-av / .chev from anvul-dash.css; the .lr-rich
   modifier reflows the row into a TYPE badge + name, a details line
   (phone · location · property type), an EPC chip, and — for solar leads
   with a postcode — a small lazy roof thumbnail. Compound selectors
   (.lead-row.lr-rich) win over dash.css regardless of load order.
   ============================================================ */
.lead-row.lr-rich { display: flex; align-items: center; gap: 14px; }
.lead-row.lr-rich .lead-av { align-self: center; }
.lead-row.lr-rich .chev { flex: none; align-self: center; }
.lead-row.lr-rich .lr-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.lead-row.lr-rich .lr-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.lead-row.lr-rich .lr-name { font-family: var(--sans); font-size: var(--text-base); font-weight: 700; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }  /* --text-base = 14.5px */
.lead-row.lr-rich .lr-when { margin-left: auto; font-family: var(--mono); font-size: var(--text-xs); color: var(--fg-faint); white-space: nowrap; flex: none; }  /* --text-xs = 11px */
.lead-row.lr-rich .lr-details { font-family: var(--mono); font-size: 11.5px; color: var(--fg-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lead-row.lr-rich .lr-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* TYPE badge — a quiet dotted pill: solar (amber) · property (signal) · enquiry (neutral) */
.lead-row.lr-rich .lr-badge { display: inline-flex; align-items: center; gap: 5px; flex: none; font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--line-strong); color: var(--fg-soft); background: var(--paper-2); white-space: nowrap; }
.lead-row.lr-rich .lr-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--fg-ghost); flex: none; }
.lead-row.lr-rich .lr-badge.lr-badge--solar { color: oklch(0.50 0.12 70); border-color: var(--warn-line); background: var(--warn-soft); }
.lead-row.lr-rich .lr-badge.lr-badge--solar::before { background: var(--warn); }
.lead-row.lr-rich .lr-badge.lr-badge--epc { color: #a8480f; border-color: var(--signal-line); background: var(--signal-soft); }
.lead-row.lr-rich .lr-badge.lr-badge--epc::before { background: var(--signal); }

/* chips — EPC (band = green / found = green / muted non-EPC), route, ASAP */
.lead-row.lr-rich .lr-chip { display: inline-flex; align-items: center; font-family: var(--mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.02em; padding: 2px 8px; border-radius: 6px; border: 1px solid var(--line); color: var(--fg-soft); background: var(--paper-2); white-space: nowrap; }
.lead-row.lr-rich .lr-chip.lr-chip--epc { color: var(--ok-ink); border-color: var(--ok-line); background: var(--ok-soft); }
.lead-row.lr-rich .lr-chip.lr-chip--noepc { color: var(--fg-faint); border-style: dashed; }
.lead-row.lr-rich .lr-chip.lr-chip--asap { color: var(--block); border-color: var(--block-line); background: var(--block-soft); font-weight: 700; }
/* source axis — calm green "Free" (every lead is free, never billed) vs the
   "Managed ad" source tag. Both are free; the tag just shows where the lead
   came from. Mirrors the backend is_paid_ad source flag (no per-lead charge). */
.lead-row.lr-rich .lr-chip.lr-chip--free { color: var(--ok-ink); border-color: var(--ok-line); background: var(--ok-soft); }
.lead-row.lr-rich .lr-chip.lr-chip--ad { color: #a8480f; border-color: var(--signal-line); background: var(--signal-soft); font-weight: 700; }
/* a lost lead stays visible but recedes — it's out of the active pipeline */
.lead-row.lr-rich.lr-dim { opacity: 0.62; }

/* solar roof thumbnail (same-origin PNG; lazy; hidden on error via JS) */
.lead-row.lr-rich .lr-thumb { width: 46px; height: 46px; flex: none; border-radius: var(--r-sm); object-fit: cover; border: 1px solid var(--line); background: var(--paper-2); }
@media (max-width: 520px) { .lead-row.lr-rich { gap: 10px; } .lead-row.lr-rich .lr-thumb { width: 40px; height: 40px; } }

/* ============================================================
   === U3 Leads/Events === (list-engine ledger boards)
   THE LEADS LEDGER — the inbox as an AUDITED page, not a marketing banner.
   Replaces the RETIRED serif-dossier masthead (editorial Source-Serif title
   + the killed radial-gradient blob + serif stat figures — all removed above).
   The headline is now the lead COUNT set as a bookkeeping SUM (the shared
   .sum/.sum-total: mono tabular + hairline-above + double-rule-beneath), with a
   mono "clause" eyebrow, a search field, and the shared anvStatRow ribbon.
   Scoped to #leadTable / [data-screen="leads"|"lead"] so it wins over the base
   .lead-row list in anvul-dash.css regardless of load order; F&L tokens only.
   ============================================================ */
[data-screen="leads"] { position: relative; }

/* ---- the ledger masthead (injected by enhanceLeadsScreen) — flat warm paper,
     no wash, closed with an editorial hairline. The count is the audited total. ---- */
.leads-ledger { margin: 2px 0 18px; padding: 2px 0 18px; border-bottom: 1px solid var(--line); display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px 20px; }
.leads-ledger .ll-head { flex: 1 1 320px; min-width: 0; }
.ll-eyebrow { display: inline-flex; align-items: center; gap: 10px; font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--signal-deep); }
.ll-eyebrow::before { content: ""; width: 18px; height: 2px; background: var(--terra); flex: none; }
.ll-tally { margin-top: 11px; }
/* the AUDITED count — the clerk's mono, sized like a headline; .sum-total gives
   the hairline-above + double-rule-beneath (the bookkeeping "audited" mark). */
.ll-count.sum { display: inline-block; font-size: clamp(26px, 4vw, 36px); font-weight: 600; letter-spacing: -0.01em; color: var(--fg); line-height: 1.15; padding: 1px 2px 4px; }
.ll-note { display: block; font-family: var(--sans); font-size: 13.5px; color: var(--fg-soft); line-height: 1.5; margin-top: 9px; max-width: 54ch; }
/* the search field — a quiet ruled input over the ledger */
.ll-search { position: relative; flex: 0 1 300px; min-width: 200px; }
.ll-search .ll-search-ic { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--fg-faint); pointer-events: none; }
.ll-search input { width: 100%; box-sizing: border-box; height: 42px; padding: 0 14px 0 38px; font-family: var(--sans); font-size: 14px; color: var(--fg); background: var(--paper); border: 1px solid var(--line-strong); border-radius: var(--r-sm); transition: border-color .15s, box-shadow .15s; -webkit-appearance: none; appearance: none; }
.ll-search input::placeholder { color: var(--fg-faint); }
.ll-search input:focus-visible { outline: none; border-color: var(--terra); box-shadow: 0 0 0 2px var(--paper), 0 0 0 4.5px var(--terra); }  /* FIX (P1-4): visible keyboard ring, not the invisible signal-soft wash */
.ll-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
/* the shared stat ribbon spans the row */
.leads-ledger .ll-stats { flex: 1 1 100%; margin-top: 2px; }
/* screen-reader-only label helper (may not exist globally) */
.visually-hidden { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ============================================================
   THE STAT RIBBON — anvStatRow() (Phase U2 SHARED PRIMITIVE).
   The Leads .leads-stats/.ls-cell component promoted to the shared,
   reusable at-a-glance ledger ribbon every engine board lacks —
   RE-TYPED into the true Fascia & Ledger voice: Bricolage display
   figures (not the Leads ribbon's retired Source Serif), the clerk's
   mono for money figures (a figure passed money:true wears .sum →
   Spline tabular), and the killed radial-gradient wash removed for
   flat warm paper with ledger hairline dividers. U3 feeds it per
   engine (Diary "today · booked · free" is the first adopter). All
   colour is a brand token; no gradient wallpaper.
   ============================================================ */
.stat-row { display: flex; flex-wrap: wrap; margin: 0 0 4px; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--paper); box-shadow: var(--shadow-sm); overflow: hidden; }
.stat-cell { flex: 1 1 0; min-width: 118px; display: flex; flex-direction: column; gap: 6px; padding: 16px 20px; border-left: 1px solid var(--line); position: relative; text-align: left; background: transparent; }
.stat-cell:first-child { border-left: 0; }
/* the figure — Bricolage display, tight, tabular; money figures also carry .sum
   (mono) which then WINS the family so takings read in the clerk's voice. */
.stat-cell .stat-v { font-family: var(--display); font-weight: 700; font-size: 30px; line-height: 0.98; letter-spacing: -0.02em; color: var(--fg); font-variant-numeric: tabular-nums; }
/* FIX (P0-2a): money MUST wear the clerk's mono. `.stat-cell .stat-v` (0,2,0) set
   --display and out-specified the bare `.sum` (0,1,0), so ribbon takings rendered
   in Bricolage, never the ledger mono. This (0,3,0) rule restores the mono voice. */
.stat-cell .stat-v.sum { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 26px; letter-spacing: -0.005em; }   /* the mono clerk sits a touch smaller to align to the display cap-height */
/* {total:true} → the AUDITED figure in the ribbon: the hairline-above + double-
   rule-beneath (the bookkeeping "settled" mark), tight so the rule hugs the money. */
.stat-cell .stat-v.sum-total { display: inline-block; align-self: flex-start; padding: 0 1px 3px; line-height: 1.12; }
.stat-cell.is-total { justify-content: flex-start; }
.stat-cell .stat-k { font-family: var(--mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint); }
/* tones — one glance names the actionable number */
.stat-cell.is-live .stat-v { color: var(--signal-deep); }
.stat-cell.is-won  .stat-v { color: var(--ok-ink); }
.stat-cell.is-warn .stat-v { color: oklch(0.50 0.12 70); }
.stat-cell.is-block .stat-v { color: var(--block); }
.stat-cell.is-live::after { content: ""; position: absolute; top: 14px; right: 16px; width: 7px; height: 7px; border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 3px var(--signal-soft); animation: lsPulse 2.4s ease-in-out infinite; }
/* a tappable cell (a <button>) — quiet until hover/focus; keyboard-reachable */
button.stat-cell { font: inherit; cursor: pointer; -webkit-appearance: none; appearance: none; border-top: 0; border-right: 0; border-bottom: 0; transition: background .15s ease; }
button.stat-cell:hover { background: var(--paper-2); }
button.stat-cell:focus-visible { outline: 2px solid var(--signal); outline-offset: -2px; }
@media (max-width: 560px) { .stat-cell { min-width: 40%; flex-basis: 40%; } .stat-cell .stat-v { font-size: 25px; } .stat-cell .stat-v.sum { font-size: 22px; } }
/* THREE cells hold ONE line at 390 (kills the 2+1 orphan wrap on the 3-cell
   Leads + Events ribbons): a 3-up basis + tighter padding + a smaller figure so
   "new · open · won" / "tonight · reserved · taken" stay on a single row. */
@media (max-width: 560px) {
  .stat-row.evt-ribbon .stat-cell, .leads-ledger .ll-stats .stat-cell { min-width: 0; flex-basis: 33.33%; padding: 13px 10px; }
  .stat-row.evt-ribbon .stat-cell .stat-v, .leads-ledger .ll-stats .stat-cell .stat-v { font-size: 21px; }
  .stat-row.evt-ribbon .stat-cell .stat-v.sum, .leads-ledger .ll-stats .stat-cell .stat-v.sum { font-size: 18px; }
  .stat-row.evt-ribbon .stat-cell .stat-k, .leads-ledger .ll-stats .stat-cell .stat-k { font-size: 9.5px; letter-spacing: 0.05em; }
}

/* ============================================================
   THE RULED PAGE (P0-1) — the console-scoped opt-in. The shipped fascia-ledger
   `.ruled` primitive drops ONE terracotta margin rule down a board; here we (a)
   re-point --rule-x into the board's left margin gutter (the homepage value is
   tuned to a viewport-centred 1180px column — wrong for a console with a sidebar),
   and (b) expose `.board-ruled` for any screen to opt in. Desktop-only by design
   (the primitive hides <720px, where a stray line would read as an error). MY
   screens adopt it below; F2/F3 add class="board-ruled" to their screens.
   ============================================================ */
[data-screen] .board-ruled, .board-ruled { position: relative; --rule-x: 14px; }
[data-screen="leads"], [data-screen="events"] { position: relative; --rule-x: 14px; }
/* opt MY screens' content into the ruled page (the fascia `.ruled::after` rule) */
[data-screen="leads"]::after, [data-screen="events"]::after, .board-ruled::after {
  content: ""; position: absolute; top: 4px; bottom: 4px; left: var(--rule-x); width: 1px;
  background: linear-gradient(180deg, rgba(199,91,57,0), rgba(199,91,57,.42) 120px, rgba(199,91,57,.42) calc(100% - 120px), rgba(199,91,57,0));
  pointer-events: none; z-index: 0; display: none;
}
@media (min-width: 720px) {
  [data-screen="leads"]::after, [data-screen="events"]::after, .board-ruled::after { display: block; }
}

/* THE NUMBERED CLAUSE-HEAD — the Ruled Page's bookkeeping voice (anvClause()). A
   mono small-caps head with a hairline rule beneath and a terracotta clause number.
   SHARED: Leads + Events open with it; F2/F3 open their groups with it. */
.clause-head { display: flex; align-items: baseline; gap: 9px; margin: 0 0 12px; padding: 0 2px 8px; border-bottom: 1px solid var(--line); }
.clause-head .clause-no { font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 0.06em; color: var(--signal-deep); font-variant-numeric: tabular-nums; flex: none; }
.clause-head .clause-label { font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-soft); }
.clause-head .clause-extra { margin-left: auto; font-family: var(--mono); font-size: 11px; font-weight: 600; color: var(--fg-faint); background: var(--paper-2); border: 1px solid var(--line); border-radius: 999px; padding: 1px 9px; min-width: 22px; text-align: center; font-variant-numeric: tabular-nums; }
/* TONIGHT is the headline clause — its rule + number wear the terracotta */
.evt-group.is-tonight .clause-head { border-bottom-color: var(--signal-line); }
.evt-group.is-tonight .clause-head .clause-label { color: var(--signal-deep); }
.evt-group.is-tonight .clause-head .clause-extra { color: #fff; background: var(--terra-deep); border-color: var(--terra-deep); }
/* the Leads masthead clause sits tight over the audited count (no bottom rule — the
   masthead already closes with its own hairline) */
.leads-ledger .ll-head > .clause-head { border-bottom: 0; padding-bottom: 0; margin-bottom: 4px; }

/* THE WALL end-stop (anvBoardClose()) — two running-bond courses beneath a board's
   last group ("the page is complete"). Subtle, quiet; reuses the .wall-course
   fascia name. Terracotta bricks (currentColor) on transparent mortar, low-contrast. */
.board-close { margin: 22px 0 2px; color: var(--terra); opacity: 0.4; }
.board-close .wall-course { height: 16px; background: transparent; overflow: hidden; }
.board-close .wall-course svg { display: block; width: 100%; height: 16px; }

/* ============================================================
   THE STATE KIT — anvSkel() / anvEmpty() / anvError() shared surfaces
   (Phase U2). One loading shimmer (wraps the .skel system in
   anvul-dash.css), one guiding empty state, one honest error card —
   so every board stops hand-rolling "Loading your X…" text + its own
   empty/error markup. Consumed across all 7 screens by U3.
   ============================================================ */
.anv-skel { display: block; }
.anv-empty { text-align: center; padding: 34px 22px 30px; color: var(--fg-soft); }
.anv-empty-ic { width: 40px; height: 40px; margin: 0 auto 12px; color: var(--fg-ghost); display: grid; place-items: center; }
.anv-empty-ic svg { width: 100%; height: 100%; }
.anv-empty-h { font-family: var(--sans); font-weight: 700; font-size: 15.5px; color: var(--fg); margin-bottom: 6px; }
.anv-empty-p { font-size: 13.5px; line-height: 1.55; margin: 0 auto; max-width: 56ch; }
.anv-empty-acts { display: flex; gap: 9px; flex-wrap: wrap; justify-content: center; margin-top: 16px; }
.anv-error { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; border-color: var(--warn-line); background: var(--warn-soft); }
.anv-error-p { margin: 0; font-size: 13.5px; color: var(--fg); line-height: 1.5; }

/* ---- filters toolbar ---- */
[data-screen="leads"] .lead-filters { margin: 0 0 14px; align-items: center; }
[data-screen="leads"] #leadCount { font-family: var(--mono); font-size: 11px; letter-spacing: 0.02em; color: var(--fg-faint); }
[data-screen="leads"] #leadExportBtn { border-radius: 999px; }

/* ---- the table becomes a stack of separated cards ---- */
#leadTable { display: flex; flex-direction: column; gap: 10px; background: transparent; border: 0; border-radius: 0; overflow: visible; }
/* the billing-summary banner + skeletons ride the same rhythm */
#leadTable > .fixcard { border-radius: var(--r); box-shadow: var(--shadow-sm); }

#leadTable .lead-row.lr-rich {
  position: relative; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r);
  padding: 15px 18px 15px 21px; gap: 15px; overflow: hidden;
  box-shadow: 0 1px 2px oklch(0.2 0.02 264 / 0.045);
  transition: transform .2s cubic-bezier(.22,.61,.36,1), box-shadow .2s ease, border-color .2s ease, background .2s ease;
}
/* the quiet left signal-rail — transparent at rest, lit for unread/hover */
#leadTable .lead-row.lr-rich::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; transition: background .2s ease; }
#leadTable .lead-row.lr-rich:hover { transform: translateY(-2px); border-color: var(--signal-line); box-shadow: var(--shadow); }
#leadTable .lead-row.lr-rich:hover::before { background: var(--signal-line); }
#leadTable .lead-row.lr-rich.unread { background: linear-gradient(90deg, var(--signal-soft), var(--paper) 58%); border-color: var(--signal-line); }
#leadTable .lead-row.lr-rich.unread::before { background: var(--signal); }
/* WON = a struck plate — a settled, sealed entry: the rail runs solid terracotta,
   the paper warms, and a small struck "Won" seal rides the name line. LOST =
   ruled through — the entry is struck off the active ledger (a line through the
   name + receded), the way a bookkeeper strikes a closed line. (Replaces the old
   soft-chip won/lost + the .lr-dim dimming.) */
#leadTable .lead-row.lr-rich.lr-won { border-color: var(--terra); background: linear-gradient(90deg, var(--signal-soft), var(--paper) 62%); }
#leadTable .lead-row.lr-rich.lr-won::before { background: var(--terra); width: 4px; }
.lead-row.lr-rich .lr-won-seal { display: inline-flex; align-items: center; gap: 4px; flex: none; margin-left: 4px; font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: #fff; background: var(--terra-deep); border: 1px solid var(--terra-deep); border-radius: 4px; padding: 2px 7px 2px 6px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.22); }
.lead-row.lr-rich .lr-won-seal svg { flex: none; }
#leadTable .lead-row.lr-rich.lr-lost { opacity: 0.62; }
#leadTable .lead-row.lr-rich.lr-lost:hover { opacity: 0.92; }
#leadTable .lead-row.lr-rich.lr-lost .lr-name { text-decoration: line-through; text-decoration-thickness: 1.5px; text-decoration-color: var(--fg-faint); color: var(--fg-soft); }
#leadTable .lead-row.lr-rich.lr-lost::before { background: var(--line-strong); }
/* FIX (P1-4): the keyboard ring was a 10%-alpha --signal-soft wash = invisible on
   white (an a11y fail on an actionable role=button row). Repaired to the VISIBLE
   double-ring anvul-dash.css already uses (paper gap + solid terracotta). */
#leadTable .lead-row.lr-rich:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--paper), 0 0 0 4.5px var(--terra), var(--shadow); }

/* avatar — the ink-on-paper MONOGRAM PLATE (P0-3): a quiet struck initials plate
   (ink glyph on the deep-paper fill JS sets), NOT a coloured confetti bubble. One
   calm treatment; terracotta is spent only on the unread signal, never a name. */
#leadTable .lead-row.lr-rich .lead-av { width: 44px; height: 44px; border-radius: 12px; font-family: var(--display); font-weight: 700; font-size: 15px; color: var(--ink); border: 1px solid var(--line-strong); box-shadow: inset 0 1px 0 rgba(255,255,255,0.55), 0 1px 2px oklch(0.2 0.02 264 / 0.08); }
/* an UNREAD lead's plate warms just slightly (the rail already carries the terra) */
#leadTable .lead-row.lr-rich.unread .lead-av { border-color: var(--signal-line); }
#leadTable .lead-row.lr-rich .lr-name { font-size: 15px; letter-spacing: -0.01em; }
#leadTable .lead-row.lr-rich .lr-thumb { width: 52px; height: 52px; border-radius: 10px; box-shadow: 0 2px 8px oklch(0.2 0.02 264 / 0.14); }
/* chevron drifts + warms on hover */
#leadTable .lead-row.lr-rich .chev { color: var(--fg-ghost); transition: transform .2s ease, color .2s ease; }
#leadTable .lead-row.lr-rich:hover .chev { transform: translateX(3px); color: var(--signal-deep); }
/* chips: a hair more breathing room + softer corners */
#leadTable .lead-row.lr-rich .lr-chip { padding: 3px 9px; border-radius: 7px; }
#leadTable .lead-row.lr-rich .lr-badge { padding: 4px 9px; }

/* ---- staggered entrance (replays gently on filter change) ---- */
@media (prefers-reduced-motion: no-preference) {
  #leadTable .lead-row.lr-rich { animation: leadIn .42s cubic-bezier(.22,.61,.36,1) both; }
  #leadTable .lead-row.lr-rich:nth-child(1) { animation-delay: .02s; }
  #leadTable .lead-row.lr-rich:nth-child(2) { animation-delay: .06s; }
  #leadTable .lead-row.lr-rich:nth-child(3) { animation-delay: .10s; }
  #leadTable .lead-row.lr-rich:nth-child(4) { animation-delay: .14s; }
  #leadTable .lead-row.lr-rich:nth-child(5) { animation-delay: .18s; }
  #leadTable .lead-row.lr-rich:nth-child(6) { animation-delay: .22s; }
  #leadTable .lead-row.lr-rich:nth-child(7) { animation-delay: .26s; }
  #leadTable .lead-row.lr-rich:nth-child(n+8) { animation-delay: .30s; }
}
@keyframes leadIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
/* (lmRise retired with the serif masthead — the ledger masthead has no arrival
   animation, so no reduced-motion leak.) lsPulse stays: the shared anvStatRow's
   .stat-cell.is-live::after still uses it. */
@keyframes lsPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ---- LEADS — PHONE (U3): the ledger masthead + shared ribbon retuned for 390px.
     The audited count steps down, the search field goes full-width above the
     ribbon, and each lead card gets phone-comfortable padding + tap size. ---- */
@media (max-width: 560px) {
  .leads-ledger { margin: 0 0 15px; padding: 2px 0 15px; gap: 12px; }
  .leads-ledger .ll-head { flex-basis: 100%; }
  .ll-search { flex-basis: 100%; }
  .ll-note { font-size: 13px; }
  #leadTable .lead-row.lr-rich { padding: 14px 15px 14px 17px; gap: 12px; }
  #leadTable .lead-row.lr-rich .lead-av { width: 42px; height: 42px; }
  /* the details line was nowrap+ellipsis; on a phone let the prepared-enquiry
     detail wrap to a second line so it's fully scannable, not truncated */
  #leadTable .lead-row.lr-rich .lr-details { white-space: normal; }
}

/* ---- empty state: a calm, considered "day one" ---- */
[data-screen="leads"] .lead-empty { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-sm); }

/* ============================================================
   LEAD DOSSIER — the detail screen, elevated.
   ============================================================ */
[data-screen="lead"] .ld-grid .card { box-shadow: var(--shadow-sm); border-radius: var(--r-lg); }
/* the demo "Example lead" banner spans the dossier grid so the two columns flow
   correctly beneath it (a real firm has no banner — the dossier sits left as designed) */
[data-screen="lead"] #leadExBanner { grid-column: 1 / -1; }
/* name is the fascia display (Bricolage, tight); the homeowner's own words are a
   pull-quote in the HOUSE voice (italic Hanken) — the Source-Serif/Georgia relic
   is retired (the master brief killed the borrowed serif; the house has no serif). */
[data-screen="lead"] [data-f=name] { font-family: var(--display); font-weight: 700; letter-spacing: -0.03em; }
[data-screen="lead"] [data-f=msg] { font-family: var(--sans); font-style: italic; font-size: 15.5px !important; line-height: 1.55; color: var(--fg-soft); }
/* the dossier avatar is the ink-on-paper monogram plate (P0-3), not a coloured bubble */
[data-screen="lead"] .lead-av { width: 52px; height: 52px; border-radius: 14px; font-size: 18px; color: var(--ink); border: 1px solid var(--line-strong); box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), 0 1px 3px oklch(0.2 0.02 264 / 0.10); }
[data-screen="lead"] .lead-who span { font-family: var(--mono); font-size: 12px; color: var(--fg-faint); }
/* CALL = the primary action on an open lead — a full-width struck plate at the
   TOP of the contact block (the reason the lead exists is to reach them; fastest
   reply wins). Wears the shared .btn.btn-primary; here we just size + place it. */
[data-screen="lead"] .lead-call-primary { display: flex; align-items: center; justify-content: center; gap: 9px; width: 100%; margin: 0 0 14px; padding: 13px 16px; font-size: 15px; text-decoration: none; }
[data-screen="lead"] .lead-call-primary svg { flex: none; }
/* the dark call-opener gets a warm signal seam + an editorial opening quote */
[data-screen="lead"] .call-opener { position: relative; background: linear-gradient(150deg, var(--ink), oklch(0.255 0.018 264)); border: 1px solid oklch(1 0 0 / 0.06); box-shadow: var(--shadow); overflow: hidden; }
[data-screen="lead"] .call-opener::before { content: "\201C"; position: absolute; top: -14px; right: 14px; font-family: var(--display); font-weight: 700; font-size: 92px; line-height: 1; color: var(--signal); opacity: 0.16; }  /* house display mark — the Libre-Caslon/Georgia relic retired */
[data-screen="lead"] .call-opener p { position: relative; }
/* the won/lost outcome card carries the same elevation as the cards */
[data-screen="lead"] .lead-decided { border-radius: var(--r); box-shadow: var(--shadow-sm); }

/* 2D roof map — the homeowner's actual roof (plain aerial, no panels), framed as
   a quiet hero in the dossier. Hidden on error via JS so it's never a fake roof. */
[data-screen="lead"] .lead-roofmap .lrm-fig { margin: 0; }
[data-screen="lead"] .lead-roofmap img { display: block; width: 100%; height: 212px; object-fit: cover; border-radius: var(--r); border: 1px solid var(--line); box-shadow: var(--shadow-sm); background: linear-gradient(135deg, var(--paper-2), var(--paper)); }
[data-screen="lead"] .lead-roofmap figcaption { font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.02em; color: var(--fg-faint); margin-top: 9px; }

/* ============================================================
   === U3 Leads/Events === (continued)
   THE BOX-OFFICE LEDGER — the events board partitioned TONIGHT / UPCOMING /
   PAST & CANCELLED (tonight pinned + emphasised; the feed is ASC so tonight used
   to sit buried under history). Each row shows "N sold · £X" (the £ is the
   paid-only figure in the clerk's .sum mono), a thin capacity bar, and a struck
   SOLD-OUT stamp — the venue's trophy, previously indistinguishable from Draft.
   F&L tokens only; no gradient wallpaper.
   ============================================================ */
/* the till-roll section heading — mono, ruled, with a count */
.evt-group { margin: 0 0 22px; }
.evt-group-h { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.evt-group-t { font-family: var(--mono); font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-soft); }
.evt-group-n { font-family: var(--mono); font-size: 11px; font-weight: 600; color: var(--fg-faint); background: var(--paper-2); border: 1px solid var(--line); border-radius: 999px; padding: 1px 9px; min-width: 22px; text-align: center; }
/* TONIGHT is the headline section — the heading rule + count wear the terracotta */
.evt-group.is-tonight .evt-group-h { border-bottom-color: var(--signal-line); }
.evt-group.is-tonight .evt-group-t { color: var(--signal-deep); }
.evt-group.is-tonight .evt-group-n { color: #fff; background: var(--terra-deep); border-color: var(--terra-deep); }

/* the event card — a box-office ledger line */
[data-screen="events"] .evt-card { position: relative; border-radius: var(--r); box-shadow: 0 1px 2px oklch(0.2 0.02 264 / 0.045); }
[data-screen="events"] .evt-card .evt-title { font-family: var(--display); font-weight: 700; font-size: 16px; letter-spacing: -0.01em; color: var(--fg); }
[data-screen="events"] .evt-card .evt-when { font-size: 13.5px; margin-top: 3px; }
[data-screen="events"] .evt-card .evt-figs { font-family: var(--sans); font-size: 13px; color: var(--fg-soft); margin-top: 4px; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
/* ticket price + the paid revenue in the clerk's mono tabular */
[data-screen="events"] .evt-card .evt-price.sum,
[data-screen="events"] .evt-card .evt-rev.sum { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; color: var(--fg); letter-spacing: -0.005em; }
[data-screen="events"] .evt-card .evt-rev.sum { color: var(--ok-ink); font-weight: 600; }
[data-screen="events"] .evt-card .evt-sold { font-weight: 600; color: var(--fg); }
[data-screen="events"] .evt-card .evt-sold--none { font-weight: 400; color: var(--fg-faint); }
[data-screen="events"] .evt-card .evt-thumb { width: 46px; height: 46px; border-radius: var(--r-sm); object-fit: cover; flex: none; border: 1px solid var(--line); }

/* TONIGHT rows — pinned + emphasised with a solid terracotta left rail */
[data-screen="events"] .evt-card--tonight { border-color: var(--signal-line); }
[data-screen="events"] .evt-card--tonight::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; border-radius: var(--r) 0 0 var(--r); background: var(--terra); }

/* the capacity bar — a thin ruled meter under the row */
[data-screen="events"] .evt-cap { margin: 9px 0 0; height: 5px; border-radius: 999px; background: var(--paper-2); border: 1px solid var(--line); overflow: hidden; max-width: 260px; }
[data-screen="events"] .evt-cap-fill { height: 100%; background: var(--fg-ghost); border-radius: inherit; transition: width .4s var(--ease, ease); }
[data-screen="events"] .evt-cap-fill.is-full { background: var(--terra); }
[data-screen="events"] .evt-cap-k { font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.02em; color: var(--fg-faint); margin-top: 5px; }

/* the STATUS stamp — SOLD OUT is a STRUCK PLATE (the venue's trophy: a solid
   terracotta plate with the signwriter's inner rule + a slight tilt), live is a
   quiet dot pill, off (cancelled) is ruled/struck-through, draft is neutral. */
[data-screen="events"] .evt-stamp { display: inline-flex; align-items: center; gap: 5px; flex: none; font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; padding: 3px 9px; border-radius: 5px; border: 1px solid var(--line-strong); color: var(--fg-soft); background: var(--paper-2); }
[data-screen="events"] .evt-stamp--live { color: var(--ok-ink); border-color: var(--ok-line); background: var(--ok-soft); }
[data-screen="events"] .evt-stamp--live::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ok-ink); flex: none; }
[data-screen="events"] .evt-stamp--off { color: var(--fg-faint); border-style: dashed; text-decoration: line-through; text-decoration-thickness: 1.5px; }
[data-screen="events"] .evt-stamp--soldout { position: relative; color: #fff; background: var(--terra-deep); border-color: var(--terra-deep); letter-spacing: 0.09em; padding: 4px 11px; transform: rotate(-2deg); box-shadow: inset 0 1px 0 rgba(255,255,255,0.22), 0 1px 3px rgba(156,65,39,0.28); }
/* the signwriter's inner rule that makes it read as a stamped plate */
[data-screen="events"] .evt-stamp--soldout::after { content: ""; position: absolute; inset: 2px; border: 1px solid rgba(255,255,255,0.32); border-radius: 3px; pointer-events: none; }
/* a sold-out card warms slightly so the whole line reads "full house" */
[data-screen="events"] .evt-card--soldout { border-color: var(--signal-line); background: linear-gradient(90deg, var(--signal-soft), var(--paper) 66%); }

/* PAST & CANCELLED — folded behind a count; the toggle is a ruled button */
.evt-group--past { margin-top: 4px; }
.evt-past-toggle { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; background: transparent; border: 0; border-top: 1px solid var(--line); padding: 14px 2px 0; cursor: pointer; color: inherit; font: inherit; }
.evt-past-toggle:focus-visible { outline: 2px solid var(--terra); outline-offset: 2px; border-radius: 4px; }
.evt-past-chev { margin-left: auto; color: var(--fg-faint); display: inline-flex; transition: transform .18s ease; }
.evt-past-toggle[aria-expanded="true"] .evt-past-chev { transform: rotate(180deg); }
.evt-past-body { margin-top: 14px; }
/* a folded past/cancelled row reads receded */
.evt-past-body .evt-card { opacity: 0.72; }
.evt-past-body .evt-card:hover { opacity: 1; }

@media (max-width: 560px) {
  [data-screen="events"] .evt-cap { max-width: none; }
  .evt-group { margin-bottom: 18px; }
}

/* ============================================================
   EVENTS BOARD COMPOSITION (U3 / R1) — the box-office row as a real ledger grid,
   the audited group take, the folded lifecycle, and the un-crushed attendees drill.
   Every colour is a brand token.
   ============================================================ */
/* THE ROW GRID — content | capacity | money | actions. On a phone it stacks; on a
   tablet/desktop these become columns so the £ + the bar sit in fixed lanes and the
   ~70% desktop void is filled (money no longer drifts to the far right). */
[data-screen="events"] .evt-card { padding: 15px 18px; margin-bottom: 12px; }
.evt-row-grid { display: flex; flex-direction: column; gap: 11px; }
.evt-main { display: flex; gap: 12px; min-width: 0; align-items: flex-start; }
.evt-main-b { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.evt-title-row { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.evt-cap-col { min-width: 0; }
.evt-cap-col:empty { display: none; }
/* the money lane — the paid take in the clerk's mono, right-anchored on desktop */
.evt-money { display: flex; flex-direction: column; gap: 2px; }
.evt-money .evt-money-v.sum { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 17px; font-weight: 650; color: var(--ok-ink); letter-spacing: -0.01em; }
.evt-money .evt-money-k { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint); }
.evt-money--none:empty { display: none; }
.evt-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* FIX (R1): the capacity-bar fill was --fg-ghost on --paper-2 = invisible below
   ~50%. Ramp it to ink-strength so a lightly-sold bar still reads; full = terra. */
[data-screen="events"] .evt-cap { background: var(--paper-2); border-color: var(--line-strong); }
[data-screen="events"] .evt-cap-fill { background: var(--fg-soft); }
[data-screen="events"] .evt-cap-fill.is-full { background: var(--terra); }

/* THE AUDITED GROUP TAKE — a double-ruled paid-only footer per group ("TONIGHT —
   £600 taken"), the precedent being hire-group-sum. Right-aligned, mono, settled. */
.evt-group-sum { display: flex; align-items: baseline; justify-content: flex-end; gap: 12px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.evt-group-sum-k { font-family: var(--mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint); }
.evt-group-sum .evt-group-sum-v.sum-total { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 15px; font-weight: 650; color: var(--ink); }
.evt-group.is-tonight .evt-group-sum-v.sum-total { color: var(--ok-ink); }

/* THE MANAGE MENU — the 4-6 lifecycle buttons fold into one quiet ⋯ menu so the
   card reads administrative, not busy. Publish stays a visible forward action. */
.evt-manage { position: relative; }
.evt-manage > summary { list-style: none; cursor: pointer; }
.evt-manage > summary::-webkit-details-marker { display: none; }
.evt-manage-btn { display: inline-flex; align-items: center; gap: 6px; }
.evt-manage-dots { font-weight: 800; letter-spacing: 0.08em; line-height: 0.4; color: var(--fg-soft); }
.evt-manage[open] > summary { border-color: var(--signal-line); color: var(--signal-deep); }
.evt-menu { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 178px; display: flex; flex-direction: column; padding: 6px; background: var(--paper); border: 1px solid var(--line-strong); border-radius: var(--r-sm); box-shadow: var(--shadow); }
.evt-menu-item { display: block; width: 100%; text-align: left; padding: 9px 12px; font-family: var(--sans); font-size: 13.5px; font-weight: 550; color: var(--fg); background: transparent; border: 0; border-radius: 7px; cursor: pointer; }
.evt-menu-item:hover { background: var(--paper-2); }
.evt-menu-item:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--signal); }
.evt-menu-item--warn { color: var(--block); }
.evt-menu-item--warn:hover { background: var(--block-soft); }

/* THE ATTENDEES DRILL — the row was an anonymous .row.between that crushed at 390
   (two-pill right column wrapped the name + split the mono ref). Now a named grid:
   name-line with a NOWRAP ref, the meta line, and a right rail that FLIPS under the
   name ≤560. Per-order £ + the door-sheet double-ruled take are added by the JS. */
.evt-att-list { padding: 4px 18px; }
.evt-att-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line); }
.evt-att-row:first-child { border-top: 0; }
.evt-att-who { min-width: 0; }
.evt-att-name { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.evt-att-name b { font-size: 14.5px; }
.evt-att-ref { font-family: var(--mono); font-size: 12px; color: var(--fg-faint); white-space: nowrap; font-variant-numeric: tabular-nums lining-nums; }
.evt-att-meta { font-size: 13px; margin-top: 3px; }
.evt-att-right { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; flex: none; }
.evt-att-money.sum { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 13.5px; font-weight: 650; color: var(--fg); }
/* the door-sheet total — the audited paid-only take, double-ruled */
.evt-att-take { display: flex; align-items: baseline; justify-content: flex-end; gap: 12px; margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--line); }
.evt-att-take-k { font-family: var(--mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint); }
.evt-att-take-v.sum-total { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 16px; font-weight: 650; color: var(--ok-ink); }

@media (max-width: 560px) {
  /* the attendees right-rail (status + paid + £) flips UNDER the name so nothing
     crushes the name/ref at 390 */
  .evt-att-row { flex-direction: column; gap: 8px; }
  .evt-att-right { justify-content: flex-start; width: 100%; }
  .evt-manage { align-self: flex-start; }
}

/* DESKTOP: the row grid becomes true lanes (content | capacity | money | actions)
   so a wide card is a ledger line, not a stretched phone card. */
@media (min-width: 834px) {
  .evt-row-grid { display: grid; grid-template-columns: minmax(0,1fr) 180px auto auto; align-items: center; gap: 16px; }
  .evt-cap-col { align-self: center; }
  [data-screen="events"] .evt-cap { margin: 0; max-width: 180px; }
  .evt-cap-col .evt-cap-k { margin-top: 5px; }
  .evt-money { align-items: flex-end; text-align: right; min-width: 74px; }
  .evt-actions { justify-content: flex-end; }
}
/* (UPCOMING 2-up considered for ≥1180px but NOT shipped: each card's own
   content|capacity|money|actions grid needs the full row width to stay a clean
   ledger line — two-up would crush those lanes. The row-grid already fills the
   desktop void, which was the real defect.) */

/* ============================================================
   ANVUL OPERATIONAL — light "coming soon" tease for the iOS app.
   Deliberately understated; pure UI, no data. Reuses .pill for the chips.
   ============================================================ */
.anvul-op { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 16px 18px; border: 1px dashed var(--line-strong); border-radius: var(--r-sm); background: var(--paper-2); }
.anvul-op-h { display: flex; align-items: flex-start; gap: 13px; min-width: 0; }
.anvul-op-mark { width: 30px; height: 30px; flex: none; border-radius: 8px; background: var(--ink); color: var(--signal); display: grid; place-items: center; }
.anvul-op-mark svg { width: 15px; height: 15px; }
.anvul-op h4 { font-family: var(--sans); font-size: 14px; font-weight: 700; margin: 0 0 3px; color: var(--fg); }
.anvul-op p { font-size: 13px; color: var(--fg-soft); margin: 0; line-height: 1.5; }
.anvul-op-chips { display: flex; gap: 7px; flex-wrap: wrap; flex: none; }
.anvul-op-chips .pill { font-size: 10px; padding: 5px 10px; }

/* ============================================================
   CONNECT YOUR OWN DOMAIN — the handoff form (#connectDomain).
   Reassuring, path-pick capture rendered by loadDomainHandoff() in
   anvul-app.js. Reuses .card / .field / .input / .seg / .chk / .btn
   atoms; the .dh-* pieces are the path options + the repeatable
   "top pages" list + the no-passwords footnote. No password field — ever.
   ============================================================ */
.dh-q { font-size: 12.5px; font-weight: 700; color: var(--fg-soft); margin: 18px 0 9px; }
.dh-opts { display: flex; flex-direction: column; gap: 10px; }
.dh-opt { display: flex; align-items: flex-start; gap: 12px; padding: 13px 15px; border: 1.5px solid var(--line-strong); border-radius: var(--r-sm); cursor: pointer; transition: border-color .15s, background .15s, box-shadow .15s; }
.dh-opt:hover { border-color: var(--signal-line); }
.dh-opt.on { border-color: var(--signal); background: var(--signal-soft); box-shadow: 0 0 0 3px var(--signal-soft); }
.dh-opt input[type="radio"] { margin-top: 2px; width: 18px; height: 18px; flex: none; accent-color: var(--signal); cursor: pointer; }
.dh-opt-b { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dh-opt-t { font-family: var(--sans); font-size: 14px; font-weight: 700; color: var(--fg); }
.dh-opt-d { font-size: 12.5px; color: var(--fg-soft); line-height: 1.5; }
.dh-reveal { margin-top: 12px; }
.dh-reveal[hidden] { display: none; }
.dh-steps { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; border: 1px dashed var(--line-strong); border-radius: var(--r-sm); background: var(--paper-2); }
.dh-step { display: flex; align-items: flex-start; gap: 11px; font-size: 13px; color: var(--fg); line-height: 1.5; }
.dh-step-n { flex: none; width: 21px; height: 21px; border-radius: 50%; display: grid; place-items: center; font-family: var(--mono); font-size: 11px; font-weight: 600; color: #fff; background: var(--signal-ink); margin-top: 1px; }
.dh-check { display: flex; align-items: flex-start; gap: 11px; margin-top: 14px; font-size: 13px; color: var(--fg); line-height: 1.5; cursor: pointer; }
.dh-check input[type="checkbox"] { margin-top: 2px; width: 18px; height: 18px; flex: none; accent-color: var(--signal); cursor: pointer; }
.dh-authorise { margin-top: 16px; padding: 13px 15px; border: 1.5px solid var(--signal-line); border-radius: var(--r-sm); background: var(--signal-soft); }
.dh-seg { margin-top: 2px; }
.dh-urls { display: flex; flex-direction: column; gap: 8px; }
.dh-url-row { display: flex; align-items: center; gap: 8px; }
.dh-url-row .input { flex: 1; min-width: 0; }
.dh-url-x { flex: none; font-size: 18px; line-height: 1; padding: 8px 12px; }
.dh-addurl { margin-top: 10px; }
.dh-submit { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 18px; }
.dh-foot { font-size: 12px; color: var(--fg-soft); line-height: 1.5; margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--line-soft); }
/* "Do it for me" (£199) value panel + the awaiting-payment note. */
.dh-value { margin-top: 12px; padding: 14px 16px; border: 1.5px solid var(--signal-line); border-radius: var(--r-sm); background: var(--signal-soft); }
.dh-value-h { font-family: var(--sans); font-size: 14.5px; font-weight: 700; color: var(--fg); margin-bottom: 5px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.dh-value p { font-size: 13px; color: var(--fg-soft); line-height: 1.55; margin: 0; }
.dh-value-done { background: var(--paper-2); }
.dh-price { font-family: var(--sans); font-size: 19px; font-weight: 800; color: var(--signal-ink); }
.dh-await { font-size: 12.5px; font-weight: 600; color: var(--signal-ink); margin: 10px 0 0; }
/* Self-guided "send these to whoever manages my site" copy/share helper. */
.dh-share { margin-top: 14px; padding: 14px 16px; border: 1px dashed var(--line-strong); border-radius: var(--r-sm); background: var(--paper-2); }
.dh-share-h { font-family: var(--sans); font-size: 13.5px; font-weight: 700; color: var(--fg); margin-bottom: 4px; }
.dh-share-pre { width: 100%; font-family: var(--mono); font-size: 12px; line-height: 1.5; resize: vertical; }
.dh-share-acts { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }

/* ============================================================
   MANAGED GOOGLE ADS (Marketing screen) — the funded-ads opt-in
   reuses the .dh-* two-path atoms + .field / .chk / .metric; these
   .mktx-* pieces are the budget input, the live dashboard grid and
   the tagged ad-leads list. Ink & Signal tokens throughout.
   ============================================================ */
.mktx-pills { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 4px; }
.mktx-form { margin: 16px 0 4px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper-2); display: flex; flex-direction: column; gap: 12px; }
.mktx-money { position: relative; max-width: 220px; }
.mktx-money .mktx-cur { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--fg-faint); font-weight: 600; pointer-events: none; }
.mktx-money .input { padding-left: 24px; }
.mktx-hint { font-size: 12px; color: var(--fg-soft); line-height: 1.5; margin: 7px 0 0; }
/* Live dashboard: compact metric cards (7 of them) flowing auto-fit. */
.mktx-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 2px; }
.mktx-grid .metric { padding: 13px 15px; }
.mktx-grid .metric .mk-l { margin-bottom: 5px; font-size: 12px; }
.mktx-grid .metric .mk-v { font-size: 23px; }
.mktx-grid .metric .mk-ctx { margin-top: 6px; }
.mktx-grid .metric.mktx-strong { border-color: var(--signal-line); background: var(--signal-soft); }
.mktx-grid .metric.mktx-strong .mk-v { color: var(--signal-deep); }
/* Tagged ad-leads list. */
.mktx-leadlist { display: flex; flex-direction: column; gap: 8px; }
.mktx-lead { display: flex; align-items: center; gap: 12px; padding: 10px 13px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); }
.mktx-lead-tag { display: inline-flex; align-items: center; gap: 5px; flex: none; font-family: var(--mono); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--signal-deep); background: var(--signal-soft); border: 1px solid var(--signal-line); border-radius: 999px; padding: 3px 9px; }
.mktx-lead-b { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.mktx-lead-b b { font-size: 14px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mktx-lead-sub { font-size: 12px; color: var(--fg-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mktx-lead .pill { flex: none; }
.mktx-empty { padding: 26px 18px; text-align: center; border: 1px dashed var(--line-strong); border-radius: var(--r-sm); background: var(--paper-2); }
.mktx-empty b { display: block; font-size: 14.5px; margin-bottom: 4px; }
.mktx-empty span { font-size: 13px; color: var(--fg-soft); display: inline-block; max-width: 52ch; }
@media (max-width: 560px) { .mktx-lead { flex-wrap: wrap; } .mktx-lead-b { order: 2; flex: 1 1 100%; } }

/* ────────────────────────────────────────────────────────────
   OVERVIEW reputation strip — the firm's REAL review count, surfaced on
   the Overview status board (renderReadinessReal in anvul-app.js). Honesty
   law: never an invented rating; :empty (pre-auth, no children) collapses it.
   ──────────────────────────────────────────────────────────── */
.rd-reviews { display: flex; align-items: center; gap: 12px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--line-soft); }
.rd-reviews:empty { display: none; }
.rd-rv-ic { width: 32px; height: 32px; border-radius: 9px; flex: none; display: grid; place-items: center; background: var(--paper); border: 1px solid var(--line-soft); color: var(--fg-faint); }
.rd-rv-ic.on { background: rgba(199, 91, 57, .10); border-color: transparent; color: var(--signal-deep); }
.rd-rv-body { flex: 1; min-width: 0; line-height: 1.3; }
.rd-rv-body b { display: block; font-size: 14px; color: var(--fg); }
.rd-rv-sub { display: block; font-size: 12px; color: var(--fg-faint); margin-top: 1px; }

/* ────────────────────────────────────────────────────────────
   REVIEWS console (Grow → Reviews) — loadReviews() in anvul-app.js.
   An honest reputation view: first-party "Verified by FreeMCS" reviews
   (moderatable) + a live Google snapshot. Reuses .card / .pill / .btn /
   .input / .seo-edu; these rv-* pieces are the review-specific atoms.
   ──────────────────────────────────────────────────────────── */
#reviewsRoot a:not(.btn) { color: var(--signal-deep); text-decoration: none; }
#reviewsRoot a:not(.btn):hover { text-decoration: underline; }
#reviewsRoot .rv-p { font-size: 13.5px; line-height: 1.55; margin: 0 0 14px; max-width: 66ch; }

/* header summary — two stat blocks split by a divider */
.rv-summary { display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch; }
.rv-sum-div { width: 1px; background: var(--line); margin: 2px 26px; }
.rv-stat { display: flex; flex-direction: column; align-items: flex-start; gap: 7px; min-width: 0; }
.rv-stat-badge { display: inline-flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--fg-soft); }
.rv-stat-badge svg { width: 15px; height: 15px; flex: none; }
.rv-stat-badge.sig { color: #a8480f; }
.rv-stat-num { font-family: var(--display); font-size: 40px; font-weight: 800; line-height: 1; color: var(--fg); letter-spacing: -.02em; }
.rv-stat-of { font-size: 17px; font-weight: 600; color: var(--fg-faint); }
.rv-stat-sub { font-size: 13px; color: var(--fg-soft); }
.rv-stat-empty { font-family: var(--display); font-size: 19px; font-weight: 700; color: var(--fg-faint); margin: 2px 0; }
.rv-stat-note { font-size: 12.5px; color: var(--fg-soft); line-height: 1.5; margin: 0 0 10px; max-width: 42ch; }

/* stars */
.rv-stars { display: inline-flex; gap: 2px; font-size: 15px; line-height: 1; }
.rv-stars.lg { font-size: 21px; }
.rv-star { color: var(--line-strong); }
.rv-star.on { color: var(--signal); }

/* MVP two-state screen (2026-07-06): the day-one hero connect card + the quiet
   verified line, replacing the stacked empty rails. High-end pass (founder
   juror review): distinct hairline icons per unlock (one accent family, green
   reserved for success notes), the review link as a crafted mono chip with
   Copy leading, per-row actions demoted to quiet text links, and "on your
   website" as a LINK to the live page — proof, not claim. */
.rv-lede { max-width: 46ch; }
.rv-hero { border: 1px solid var(--signal-line); background: linear-gradient(180deg, var(--paper), var(--signal-soft)); }
.rv-unlocks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.rv-unlocks li { display: flex; gap: 11px; align-items: flex-start; font-size: 13.5px; line-height: 1.5; color: var(--fg); max-width: 62ch; }
.rv-un-ic { flex: none; width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center;
  background: var(--paper); border: 1px solid var(--signal-line); color: var(--signal-deep); margin-top: -2px; }
.rv-un-ic svg { width: 15px; height: 15px; }
.rv-quiet { display: flex; gap: 11px; align-items: center; font-size: 13px; line-height: 1.55; }
.rv-site-link { display: inline-flex; align-items: center; gap: 7px; margin-top: 9px; font-size: 12.5px; font-weight: 700;
  color: var(--signal-deep); }
.rv-site-link svg { width: 14px; height: 14px; }
.rv-link-chip { display: flex; align-items: center; gap: 8px; padding: 10px 13px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--paper-2); color: var(--fg-soft); min-width: 0; }
.rv-link-chip svg { width: 14px; height: 14px; flex: none; color: var(--fg-faint); }
.rv-link-txt { font-family: var(--mono); font-size: 12px; letter-spacing: 0; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; min-width: 0; }
.rv-item-acts { display: flex; align-items: center; gap: 16px; margin-top: 8px; }
.rv-act-link { background: none; border: 0; padding: 0; cursor: pointer; font-family: var(--sans); font-size: 12.5px;
  font-weight: 700; color: var(--signal-deep); text-decoration: none; }
.rv-act-link:hover { text-decoration: underline; }
.rv-act-quiet { color: var(--fg-faint); font-weight: 600; }
.rv-act-quiet:hover { color: var(--fg-soft); }
@media (max-width: 560px) {
  /* the "one tap" pill wrapped against the heading on phones — heading first,
     pill quietly beneath it, never side-by-side squeeze. #reviewsRoot bumps
     specificity over `.between` (defined in the later-loading dash sheet). */
  #reviewsRoot .rv-req-head { flex-direction: column; align-items: flex-start; gap: 6px; }
}
@media (max-width: 920px) {
  /* scroll clearance so the last card's actions can rise above the +Ask FAB */
  .screen[data-screen="reviews"] #reviewsRoot { padding-bottom: 92px; }
}

/* one-tap review link + auto-on-won note */
.rv-link-row { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }
.rv-link-row .input { flex: 1; min-width: 220px; font-size: 13px; color: var(--fg-soft); }
.rv-auto { display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; padding: 12px 14px; background: var(--ok-soft); border: 1px solid var(--ok-line); border-radius: var(--r-sm); font-size: 13px; color: var(--fg); line-height: 1.5; }
.rv-auto-ic { flex: none; width: 20px; height: 20px; border-radius: 50%; background: var(--ok); color: #fff; display: grid; place-items: center; margin-top: 1px; }
.rv-auto-ic.warn { background: var(--warn); }
.rv-auto-ic svg { width: 12px; height: 12px; }

/* review list + items */
.rv-list { margin-top: 8px; }
.rv-item { padding: 15px 0; border-bottom: 1px solid var(--line-soft); }
.rv-item:last-child { border-bottom: 0; }
.rv-item.is-hidden { opacity: .6; }
.rv-item-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rv-act { margin-left: auto; }
.rv-when { font-size: 12px; color: var(--fg-faint); }
.rv-by-inline { font-weight: 700; font-size: 13.5px; color: var(--fg); }
.rv-vbadge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700; letter-spacing: .02em; color: var(--ok-ink); }
.rv-vbadge svg { width: 13px; height: 13px; }
.rv-text { font-size: 14px; line-height: 1.55; color: var(--fg); margin: 9px 0 6px; }
.rv-photo { display: block; margin: 8px 0 6px; max-width: 220px; max-height: 160px; width: auto; border-radius: 10px; border: 1px solid var(--line); object-fit: cover; }
.rv-by { font-size: 12.5px; color: var(--fg-soft); }
.rv-hidden-tag { font-size: 12px; color: var(--fg-faint); font-style: italic; }
.rv-hidden-wrap { margin-top: 12px; }
.rv-hidden-wrap summary { cursor: pointer; font-size: 12.5px; color: var(--fg-soft); padding: 6px 0; }

/* claim-safe Google reply draft */
.rv-reply-out { margin-top: 10px; }
.rv-draft { background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 13px 14px; }
.rv-draft-h { font-size: 11px; font-family: var(--mono); letter-spacing: .04em; text-transform: uppercase; color: var(--signal-deep); margin-bottom: 7px; }
.rv-pre { white-space: pre-wrap; font-size: 13px; line-height: 1.55; color: var(--fg); }
.rv-draft-acts { margin-top: 10px; }
.rv-draft-note { display: flex; gap: 8px; align-items: flex-start; font-size: 12px; color: var(--fg-soft); line-height: 1.5; margin: 11px 0 0; }

/* empty states */
.rv-empty { display: flex; gap: 13px; align-items: flex-start; padding: 14px 0 4px; }
.rv-empty-ic { flex: none; width: 36px; height: 36px; border-radius: 50%; background: var(--signal-soft); color: var(--signal-deep); display: grid; place-items: center; }
.rv-empty-ic svg { width: 18px; height: 18px; }
.rv-empty b { font-size: 14.5px; }
.rv-empty p { font-size: 13px; color: var(--fg-soft); line-height: 1.5; margin: 4px 0 0; max-width: 60ch; }

/* cross-link to the off-page engine */
.rv-xlink { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.rv-xlink b { font-size: 14.5px; }

@media (max-width: 720px) {
  .rv-summary { grid-template-columns: 1fr; }
  .rv-sum-div { width: auto; height: 1px; margin: 18px 0; }
}

/* ===== Showcase (Grow → Showcase): real completed jobs → case studies =====
   The firm's own projects grid + the add/edit form (in the shared .anv-modal).
   Reuses .card / .pill / .btn / .field / .input / .seo-edu / .req-thumb /
   .dh-check / .fixcard wherever possible; these sc-* pieces are the
   showcase-specific layout only. */
.sc-head { margin: 22px 0 14px; gap: 14px; }
.sc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.sc-card { display: flex; flex-direction: column; overflow: hidden; }
.sc-card-media { position: relative; aspect-ratio: 16 / 10; background: var(--paper-2); }
.sc-card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sc-media-count { position: absolute; right: 8px; bottom: 8px; font-family: var(--mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.03em; color: #fff; background: rgba(20,20,19,0.74); padding: 3px 8px; border-radius: 999px; }
.sc-card-media-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px; color: var(--fg-ghost); }
.sc-card-media-empty svg { width: 30px; height: 30px; }
.sc-card-media-empty span { font-size: 12px; font-weight: 600; }
.sc-card-body { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px 18px; flex: 1; }
.sc-card-top { align-items: center; gap: 10px; }
.sc-card-meta { font-family: var(--mono); font-size: 11px; letter-spacing: 0.03em; text-transform: uppercase; color: var(--fg-soft); }
.sc-card-title { font-family: var(--display); font-size: 16px; font-weight: 700; letter-spacing: -0.01em; margin: 0; }
.sc-card-sum { font-size: 13px; color: var(--fg-soft); line-height: 1.5; margin: 0;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.sc-card-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; padding-top: 6px; }
.sc-card-acts .sc-del { margin-left: auto; color: var(--block); }

/* honest empty state */
.sc-empty { text-align: center; max-width: 520px; margin: 0 auto; }
.sc-empty-ic { width: 56px; height: 56px; margin: 4px auto 14px; border-radius: 50%; display: grid; place-items: center; background: var(--signal-soft); color: var(--signal-ink); }
.sc-empty-ic svg { width: 28px; height: 28px; }
.sc-empty p { font-size: 14.5px; color: var(--fg-soft); line-height: 1.55; margin: 0 0 16px; }

/* add / edit form (inside the shared .anv-modal) */
.sc-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.sc-photos { margin-bottom: 16px; }
.sc-photos .req-thumbs:not(:empty) { margin: 4px 0 10px; }
.sc-photo-add { width: max-content; }
.sc-existing { margin: 4px 0 10px; }
.sc-existing-l { display: block; font-size: 11.5px; font-weight: 700; color: var(--fg-soft); margin-bottom: 6px; }
.sc-noc { outline: 2px solid var(--block-line); }
.sc-noc-b { position: absolute; left: 2px; bottom: 2px; font-size: 8.5px; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: #fff; background: var(--block); padding: 1px 4px; border-radius: 4px; }
/* the REQUIRED consent gate — highlighted (reuses .dh-check for layout) so it
   reads as the gate it is */
.sc-consent { margin-top: 4px; padding: 13px 15px; border: 1.5px solid var(--signal-line); border-radius: var(--r-sm); background: var(--signal-soft); }
.sc-msg.err { color: var(--block); }
.sc-msg.ok { color: var(--ok-ink); }

@media (max-width: 560px) { .sc-form-row { grid-template-columns: 1fr; } }

/* ===== CHOOSE A DESIGN — the 13-skin chooser (firm Requests area). Each card is
   the firm's OWN site re-rendered in one skin (a scaled live iframe thumbnail);
   "Use this design" files a new_skin concierge request. ===== */
.design-gallery { margin-top: 2px; }
.design-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.design-card { max-width: 100%; min-width: 0; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--card, #fff); display: flex; flex-direction: column; }
.design-card.on { border-color: var(--ok-line); box-shadow: 0 0 0 1px var(--ok-line); }
/* Fluid thumbnail: the frame holds the desktop 1280:940 ratio at ANY card width;
   the iframe renders at 1280px and is downscaled by --dz-scale (= frame width /
   1280), set per-frame in JS — CSS can't derive a unitless scale from a fluid
   width. The ~0.19 fallback covers the 240px min before JS measures. */
.design-frame { position: relative; display: block; width: 100%; aspect-ratio: 1280 / 940; overflow: hidden; border-bottom: 1px solid var(--line); background: #f4f4f2; }
.design-frame iframe { width: 1280px; height: 940px; border: 0; transform: scale(var(--dz-scale, 0.1875)); transform-origin: top left; pointer-events: none; }
.design-frame .design-open { position: absolute; inset: 0; display: flex; align-items: flex-end; justify-content: center; padding-bottom: 10px; opacity: 0; transition: opacity .15s; background: linear-gradient(transparent 58%, rgba(0,0,0,.4)); color: #fff; font-size: 12px; font-weight: 700; }
.design-frame:hover .design-open { opacity: 1; }
.design-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; }
.design-name { font-size: 13.5px; font-weight: 700; color: var(--ink, #1a1a1a); }

/* ===== Finish-your-site onboarding checklist (reuses the .chk row styling). ===== */
.ob-up { cursor: pointer; }
.ob-colour { width: 40px; height: 30px; padding: 2px; border: 1px solid var(--line); border-radius: 7px; background: #fff; cursor: pointer; }
.ob-jobform { margin: 0 0 4px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--paper, #faf9f6); }
.ob-submit { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-soft, var(--line)); }
.ob-must-l { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.ob-submit textarea { width: 100%; }
.ob-built { padding: 6px 2px; }
.ob-built b { font-size: 14.5px; }

/* Claim landing: the firm's real site, framed beside the passcode login. */
.auth-preview { margin-top: 14px; border-radius: 10px; overflow: hidden; border: 1px solid rgba(255,255,255,.18); background: #fff; box-shadow: 0 8px 30px rgba(0,0,0,.25); }
.auth-preview-bar { display: flex; gap: 5px; padding: 8px 10px; background: rgba(0,0,0,.06); border-bottom: 1px solid rgba(0,0,0,.08); }
.auth-preview-bar i { width: 9px; height: 9px; border-radius: 50%; background: rgba(0,0,0,.18); }
.auth-preview iframe { width: 100%; height: 320px; border: 0; display: block; background: #fff; }

/* Review-&-approve: the firm's finished site framed for sign-off. */
.ob-review-frame { margin-top: 12px; border-radius: 10px; overflow: hidden; border: 1px solid var(--line); }
.ob-review-frame iframe { width: 100%; height: 300px; border: 0; display: block; background: #fff; }

/* Multi-service smart-questions chooser. */
.sq-group { margin-bottom: 16px; }
.sq-group-h { font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.sq-row { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line-soft, var(--line)); }
.sq-row:first-of-type { border-top: 0; }
.sq-ck { margin-top: 11px; flex: none; }
.sq-body { flex: 1; min-width: 0; }
.sq-body .sq-o { margin-top: 5px; font-size: 12.5px; }
.sq-intel { display: block; font-size: 11.5px; color: var(--fg-soft); margin-top: 4px; }

/* ---- Diary & Booking (App Store diary engine) — LAYOUT ONLY; every colour is a
   brand token (terracotta --signal family), never a hardcoded value. ---- */
/* DAY-NAV SCOPE FIX (Phase U3): the .diary-bar / .diary-daynav layout was
   scoped to diary + catalogue only, so the reservations day-pager (now wrapped
   in the same .seg .diary-daynav) rendered unstyled. Widen the two rules to
   the reservations screen too. */
[data-screen="diary"] .diary-bar, [data-screen="reservations"] .diary-bar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
[data-screen="diary"] .diary-daynav button, [data-screen="reservations"] .diary-daynav button { min-width: 42px; }
[data-screen="diary"] .diary-daynav #diaryDayLabel, [data-screen="reservations"] .diary-daynav #resvDayLabel { min-width: 92px; }
[data-screen="diary"] .diary-cols { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
[data-screen="diary"] .diary-col { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r); padding: 12px; }
[data-screen="diary"] .diary-col-h { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
[data-screen="diary"] .diary-col-empty { font-size: 13px; margin: 4px 2px 0; }
/* UX-EDGE: native ticks/dates/times carry the brand, not browser-blue —
   the .dh-opt radios already did this; checkboxes and pickers now match. */
input[type="checkbox"], input[type="date"], input[type="time"] { accent-color: var(--signal); }
[data-screen="diary"] .diary-card { border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px 12px; margin-bottom: 8px; background: var(--paper-2); }
[data-screen="diary"] .diary-card:last-child { margin-bottom: 0; }
[data-screen="diary"] .diary-tray .diary-card { background: var(--signal-soft); border-color: var(--signal-line); }
[data-screen="diary"] .diary-card-main { font-size: 14px; display: flex; flex-direction: column; gap: 2px; }
[data-screen="diary"] .diary-card-sub { font-size: 12.5px; }
[data-screen="diary"] .diary-card-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; align-items: center; }
[data-screen="diary"] .diary-cancelled .diary-card-main, [data-screen="diary"] .diary-no_show .diary-card-main { opacity: .55; text-decoration: line-through; }
[data-screen="diary"] .diary-completed { border-color: var(--ok-line); }
[data-screen="diary"] .diary-assign, [data-screen="diary"] .diary-res-name, [data-screen="diary"] .diary-res-add input, [data-screen="diary"] .diary-res-add select { font-family: var(--sans); font-size: 13.5px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); color: var(--fg); }
[data-screen="diary"] .diary-res-list { display: flex; flex-direction: column; gap: 8px; }
[data-screen="diary"] .diary-res-row { display: flex; align-items: center; gap: 8px; }
[data-screen="diary"] .diary-res-name { flex: 1; min-width: 0; }
[data-screen="diary"] .diary-res-add { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
[data-screen="diary"] .diary-res-add input[name="name"] { flex: 1; min-width: 160px; }
@media (max-width: 480px) { [data-screen="diary"] .diary-cols { grid-template-columns: 1fr; } }

/* ---- Orders + Reservations engine boards — reuse the diary card language,
   scoped to their own screens (the diary rules above are diary-only). ---- */
[data-screen="orders"] .diary-card-acts, [data-screen="reservations"] .diary-card-acts { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
[data-screen="orders"] .diary-completed, [data-screen="orders"] .diary-ready { border-color: var(--signal-line); }
[data-screen="orders"] .diary-cancelled, [data-screen="reservations"] .diary-cancelled, [data-screen="reservations"] .diary-no_show { opacity: .6; }
[data-screen="reservations"] .diary-cancelled b, [data-screen="reservations"] .diary-no_show b { text-decoration: line-through; }
[data-screen="reservations"] .diary-completed { border-color: var(--ok-line); }
.ord-card .row.between b { font-size: 15px; }
.ord-lines { margin: 8px 0 2px; border-top: 1px solid var(--line); padding-top: 8px; }
/* A BILL LINE with a dotted LEADER: item ·········· £14.00. The leader is the
   ledger-true anchor — it bridges item→figure so the £ never floats in a wide
   void on a desktop card (the R1 "£ drifts 900px" P0). Baseline-aligned so the
   dots sit on the type baseline like a printed invoice. */
.ord-line { display: flex; align-items: baseline; gap: 8px; font-size: 13.5px; padding: 2px 0; }
.ord-line .ord-line-lbl { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ord-line .ord-leader { flex: 1 1 auto; min-width: 14px; align-self: stretch;
  border-bottom: 1px dotted var(--line-strong); transform: translateY(-4px); opacity: .7; }
.ord-line .sum { flex: none; white-space: nowrap; }
.ord-line-note { font-size: 12px; padding-left: 2px; margin-top: -1px; }
/* Discount line in the money strip — a credit, so it reads in the signal accent. */
.ord-line--disc { color: var(--signal-deep, #a8472a); font-weight: 600; }
.ord-sub { font-size: 12.5px; }
.ord-note { font-size: 13px; margin-top: 8px; font-style: italic; }
.ord-filters { display: flex; flex-wrap: wrap; gap: 8px; }
.ord-filters .btn[aria-pressed="true"] { background: var(--signal-soft); border-color: var(--signal-line); color: #a8480f; }
[data-screen="reservations"] .diary-res-add { display: flex; gap: 8px; flex-wrap: wrap; }
[data-screen="reservations"] .diary-res-add input { font-family: var(--sans); font-size: 13.5px; padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); color: var(--fg); }
[data-screen="reservations"] .diary-res-add input[name="name"] { flex: 1; min-width: 160px; }

/* ---- Catalogue (Diary Layer 4 — the firm's services / menu) — LAYOUT ONLY;
   every colour is a brand token (terracotta --signal family). ---- */
[data-screen="catalogue"] .diary-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
[data-screen="catalogue"] .cat-thumb { flex: 0 0 auto; width: 62px; height: 62px; border-radius: var(--r-sm); background-size: cover; background-position: center; background-color: var(--paper-2); border: 1px solid var(--line); display: inline-flex; align-items: center; justify-content: center; }
[data-screen="catalogue"] .cat-thumb-empty { color: var(--signal); }
[data-screen="catalogue"] .cat-f { display: flex; flex-direction: column; gap: 5px; font-size: 13px; }
[data-screen="catalogue"] .cat-f > span { font-weight: 600; }
[data-screen="catalogue"] .cat-f em { font-weight: 400; font-style: normal; }
[data-screen="catalogue"] .cat-f input, [data-screen="catalogue"] .cat-f textarea, [data-screen="catalogue"] .cat-f select,
[data-screen="catalogue"] #catSeedForm input[name="url"] { font-family: var(--sans); font-size: 14px; padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); color: var(--fg); width: 100%; box-sizing: border-box; }
[data-screen="catalogue"] .cat-f textarea { resize: vertical; }
@media (max-width: 560px) {
  [data-screen="catalogue"] .cat-item { flex-wrap: wrap; }
  [data-screen="catalogue"] .cat-item > .row { max-width: none !important; justify-content: flex-start !important; }
}

/* ═══ E-COMMERCE (2026-07-19): STOCK · VARIANTS · DISPATCH — Fascia & Ledger ═══
   Money reads as audited bookkeeping: the clerk's mono, tabular figures (.mono
   .tnum on every figure in the JS), and an order's TOTAL takes THE SUM's
   double rule — the 500-year-old "this number is checked" mark rivals can't
   wear. Terracotta (--signal) throughout; reuses the console's card/pill/input
   language — no new component system. */
/* THE SUM — the order total wears the SHARED .sum .sum-total primitive
   (fascia-ledger.css: mono tabular + hairline-above + 3px double-rule-beneath —
   the audited-total mark). This is the reference adoption: what was a LOCAL
   double-rule copy is now the shared class. .ord-total keeps ONLY the geometry
   the shared span rule can't give a <b> (inline-block + the total's weight/pad);
   the rule + mono come from .sum/.sum-total. */
.ord-card .ord-total{
  display: inline-block; font-weight: 650;
  padding: 1px 1px 3px; line-height: 1.25;
}
/* the dispatch beat — the "Dispatched · date · tracking" row under the header */
.ord-card .ord-dispatch{ margin: 6px 0 2px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ord-card .ord-dispatch .mono{ color: var(--fg-soft); letter-spacing: .02em; }
/* the inline tracking-number capture (no modal — the card's own footer) */
.ord-card .ord-ship-form{ margin: 10px 0 2px; padding: 12px; border: 1px solid var(--signal-line); border-radius: var(--r-sm); background: var(--signal-soft); }
.ord-card .ord-ship-form input[data-ord-track]{ font-family: var(--mono); letter-spacing: .02em; }

/* VARIANTS — the option manager inside the catalogue editor */
[data-screen="catalogue"] .cat-variants{ border-top: 1px solid var(--line); padding-top: 14px; }
[data-screen="catalogue"] .cat-variant-row{
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper);
}
[data-screen="catalogue"] .cat-variant-row .mono{ font-variant-numeric: tabular-nums lining-nums; }
[data-screen="catalogue"] .cat-vform{ border: 1px solid var(--signal-line); background: var(--signal-soft); }
@media (max-width: 560px){
  [data-screen="catalogue"] .cat-variant-row{ align-items: flex-start; }
  [data-screen="catalogue"] .cat-variant-row > .row{ width: 100%; }
}

/* ═══ CONSOLE BOARDS LEVEL (UX audit 2026-07-14) ═══ */
/* status colour system — one glance tells the state */
.diary-card.diary-held,.dg-ev.diary-held{border-left:3px solid #c99a2e}
.diary-card.diary-booked,.dg-ev.diary-booked,.card.diary-received{border-left:3px solid var(--signal,#c75b39)}
.card.diary-confirmed,.card.diary-preparing{border-left:3px solid #2e6fc9}
.card.diary-ready{border-left:3px solid #2f7d57}
.diary-card.diary-completed,.dg-ev.diary-completed,.card.diary-completed{border-left:3px solid #9aa0a6;opacity:.82}
.diary-card.diary-cancelled,.diary-card.diary-no_show,.dg-ev.diary-cancelled,.dg-ev.diary-no_show,.card.diary-cancelled{border-left:3px solid #b3423a;opacity:.62}
/* E-COMMERCE: a dispatched (posted) order — the ok green, like a fulfilled beat */
.card.diary-shipped{border-left:3px solid var(--ok,#2f7d57)}
.ord-late{color:#b3423a}
/* the time-grid day view */
.dg{display:flex;gap:0;border:1px solid var(--line,#e5e2da);border-radius:14px;background:var(--paper,#fff);overflow:auto;padding:14px 10px 18px}
.dg-axis{position:relative;width:52px;flex:none;height:calc(var(--dgh) + 34px);margin-top:34px}
.dg-hour{position:absolute;left:0;right:0;font-size:10.5px;color:var(--ink-3,#8a857c);font-variant-numeric:tabular-nums}
.dg-hour span{position:relative;top:-7px}
.dg-cols{display:flex;gap:10px;flex:1;min-width:0}
.dg-col{flex:1;min-width:170px}
.dg-lane{position:relative;height:var(--dgh);border-left:1px dashed var(--line,#e5e2da);
  background:repeating-linear-gradient(to bottom,transparent 0,transparent 65px,var(--line,#e5e2da) 65px,var(--line,#e5e2da) 66px)}
.dg-ev{position:absolute;left:6px;right:4px;background:var(--paper-2,#faf8f4);border:1px solid var(--line,#e5e2da);
  border-radius:9px;padding:5px 8px;font-size:12px;line-height:1.35;overflow:hidden;box-shadow:0 6px 14px -10px rgba(28,27,25,.35)}
.dg-ev b{font-variant-numeric:tabular-nums}
.dg-ev .dg-ev-sub{display:block;font-size:10.5px;color:var(--ink-3,#8a857c)}
.dg-ev .diary-card-acts{margin-top:4px;display:flex;gap:4px;flex-wrap:wrap}
.dg-ev .diary-card-acts .btn{padding:2px 8px;font-size:10.5px;min-height:0}
.dg-now{position:absolute;left:0;right:0;height:0;border-top:2px solid var(--signal,#c75b39);z-index:2}
.dg-now i{position:absolute;left:-5px;top:-5px;width:8px;height:8px;border-radius:50%;background:var(--signal,#c75b39)}
/* P1-5 (2026-07-20): the current-time rule is drawn per lane; bleed each lane's
   line across the inter-column gap (10px desktop / 8px phone) so the separate
   dashes join into ONE continuous rule across the whole grid. The last column
   stops at its own edge (nothing to bridge to). Only the dot leads the row. */
.dg-col:not(:last-child) .dg-lane .dg-now{right:-10px}
.dg-col:not(:first-child) .dg-lane .dg-now i{display:none}

/* ═══ PANEL P0-1 (readiness panel 2026-07-14): the day grid becomes operable ═══
   Cards size their lockup to their height — a 30-min card is ~31px tall, so it
   gets ONE ellipsised line instead of clipping meta mid-glyph; 45-min keeps two
   clean lines; only ≥60-min carries the inline action row. Every card is a tap
   target (the detail sheet holds the full action row for the rest). */
.dg-ev{cursor:pointer}
.dg-ev:hover{border-color:var(--signal-line,#e8c9bb)}
.dg-ev:focus-visible{outline:2px solid var(--signal,#c75b39);outline-offset:1px}
.dg-ev--s{white-space:nowrap;text-overflow:ellipsis;padding-top:4px;padding-bottom:4px}
.dg-ev--s .dg-ev-sub{display:inline;margin-left:5px}
.dg-ev--s .diary-card-acts,.dg-ev--m .diary-card-acts{display:none}
/* keep the ≥60-min inline row inside its 64px box (worst case: visit pill line) */
.dg-ev .diary-card-acts{margin-top:3px}
.dg-ev .pill{font-size:10px;padding:1px 7px}
/* ═══ P0-4 (2026-07-20): the visit-chip meta line was never budgeted. A 45–59-min
   card is ~47px tall = two lines, but time+name / VISIT-pill / sub is THREE →
   the sub was sliced ("45 min · Done · £2…"). The chip is secondary (it's on the
   detail sheet), so drop it on compact (<60-min) cards, and clamp the name row
   to a single ellipsised line so it can never wrap and push the sub past the clip.
   A card now renders only the lines its height can hold — no mid-line slicing. */
.dg-ev--s .pill,.dg-ev--m .pill{display:none}
.dg-ev--m{white-space:nowrap}
.dg-ev--m>b,.dg-ev--m{overflow:hidden;text-overflow:ellipsis}
.dg-ev--m .dg-ev-sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* a split (side-by-side) card is half/third width — keep its text on clean lines
   too so the narrow lane never slices a glyph; the figure rides its own line. */
.dg-ev--split{white-space:normal}
.dg-ev--split .pill{display:none}
.dg-ev--split.dg-ev--s{white-space:nowrap}

/* ═══ PANEL P0-2: blocked time — the owner's own struck-out hours ═══
   Neutral diagonal hatch on --line tones; never the terracotta booked accent,
   never a status word, never customer verbs. */
.dg-ev.dg-ev--block{
  background:repeating-linear-gradient(135deg,transparent 0 6px,var(--line,#e5e2da) 6px 7px) var(--paper-2,#faf8f4);
  border-left:3px solid var(--line-strong,#cfcabf);
}
.dg-ev.dg-ev--block,.dg-ev.dg-ev--block b{color:var(--fg-soft,#5f5b52)}

/* ═══ PANEL P0-1: the event detail sheet ═══
   Anchored popover beside the card on desktop (≥720px, JS sets left/top);
   a bottom sheet on mobile. Scrim always catches the dismiss tap. */
.dgev-scrim{position:fixed;inset:0;z-index:120;background:oklch(0.18 0.03 264 / 0.1)}
.dgev-sheet{
  position:fixed;width:min(360px,calc(100vw - 24px));max-height:min(72vh,540px);overflow:auto;
  background:var(--paper,#fff);border:1px solid var(--line,#e5e2da);border-radius:14px;
  box-shadow:0 18px 48px -12px rgba(28,27,25,.35),0 4px 14px rgba(28,27,25,.12);
  padding:16px 16px 14px;animation:anvPop .22s cubic-bezier(.18,1.2,.4,1) both;
}
.dgev-sheet:focus{outline:none}
.dgev-sheet--block{background:repeating-linear-gradient(135deg,transparent 0 8px,oklch(0.9 0.005 84 / 0.5) 8px 9px) var(--paper,#fff)}
.dgev-meta{display:flex;flex-direction:column;gap:6px;margin:12px 0 2px}
.dgev-row{display:flex;gap:10px;font-size:13.5px;line-height:1.45}
.dgev-k{flex:0 0 62px;color:var(--ink-3,#8a857c);font-size:12px;padding-top:1px}
.dgev-v{min-width:0;overflow-wrap:anywhere}
.dgev-acts{margin-top:12px;padding-top:12px;border-top:1px solid var(--line,#e5e2da)}
.dgev-acts:empty{display:none}
/* the sheet lives on <body> (outside [data-screen="diary"]) — its move form
   carries the same console input language + the 44px picker standard here */
.dgev-sheet .diary-res-add input{font-family:var(--sans);font-size:13.5px;padding:8px 10px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);color:var(--fg)}
.dgev-sheet select,.dgev-sheet input[type="date"],.dgev-sheet input[type="time"]{min-height:44px}
@media (max-width:719.98px){
  .dgev-scrim{background:oklch(0.18 0.03 264 / 0.4)}
  .dgev-sheet{
    left:0;right:0;top:auto;bottom:0;width:auto;max-height:76vh;
    border-radius:16px 16px 0 0;border-left:0;border-right:0;border-bottom:0;
    padding-bottom:calc(16px + env(safe-area-inset-bottom));
  }
  /* one-thumb targets in the sheet (house 44px standard) */
  .dgev-acts .btn{min-height:44px}
}
@media (prefers-reduced-motion: reduce){ .dgev-sheet{animation:none} }

/* ═══ PANEL P1-4 — VERIFIED REAL at 390×844 (scroll sweep, 2 and 5 held
   fixtures): the Ask FAB fully covered a day-grid card (77×31px — now a tap
   target for the detail sheet) at scroll 240–320, and clipped the tray's Move
   at several offsets. The diary at mobile is wall-to-wall actions, so the FAB
   stands down there — Care keeps its own bottom-bar tab one thumb away. Same
   body:has() idiom as the checklist / intake / pricing suppressions
   (anvul-dash.css); higher specificity beats the dash display rule. ═══ */
@media (max-width: 920px){
  body:has(.screen[data-screen="diary"][data-active]) .care-fab{display:none}
  /* R1: reservations is the same wall-to-wall-actions board on a phone/tablet —
     the Ask FAB overlapped its rows at ≤834, so it stands down here too (added to
     the shared suppression selector list; Care keeps its bottom-bar tab). */
  body:has(.screen[data-screen="reservations"][data-active]) .care-fab{display:none}
}

/* ═══ PANEL nit-6: primary-flow pickers in the diary hit the 44px house
   standard (they measured 41px; AA floor passed but the house bar is 44). ═══ */
[data-screen="diary"] select,
[data-screen="diary"] input[type="date"],
[data-screen="diary"] input[type="time"]{min-height:44px}

/* ═══ DIARY — PHONE ELEVATION (2026-07-16). At 390px the day-grid was tight:
   a 170px min-width column plus the 52px axis left the grid horizontally
   scrolling and the cards cramped. On phones the grid goes full-bleed to the
   content gutters, the axis narrows, the hour rows breathe a touch more, event
   cards get comfortable type + a clear left status rail, and — for the common
   single-resource firm — the one column simply fills the width (no sideways
   scroll). Two+ resources keep a gentle horizontal scroll with snap, so a
   multi-chair shop can still swipe between columns one-handed. ═══ */
@media (max-width: 560px) {
  [data-screen="diary"] .dg {
    /* bleed to the content's side gutter (20px at <=600px, set by the winning
       `.app .content` rule in anvul-screens.css) so the grid uses the full width */
    margin-left: -20px; margin-right: -20px; border-radius: 0;
    border-left: 0; border-right: 0; padding: 12px 14px 16px;
    gap: 0; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
  }
  /* the hour axis stays pinned as you swipe between chairs so a time always has
     its label; it sits above the cards but below the day-total plate */
  [data-screen="diary"] .dg-axis { width: 42px; margin-top: 30px; position: sticky; left: 0; z-index: 3; background: var(--paper, #fff); }
  [data-screen="diary"] .dg-hour { font-size: 11px; }
  [data-screen="diary"] .dg-cols { gap: 8px; }
  /* P0-2 (2026-07-20): the lanes MUST have a real width on a phone. With >1
     chair each column is a comfortable swipe width and the grid scrolls
     horizontally (snap already set on `.dg-cols`); the SOLO barber's single
     column keeps the full width (no sideways scroll). Was `min-width:0` with
     `flex:1`, which starved every multi-chair lane to 0px. */
  [data-screen="diary"] .dg-col { flex: 0 0 min(78vw, 300px); min-width: 0; scroll-snap-align: start; }
  [data-screen="diary"] .dg-col:only-child { flex: 1 1 auto; }
  [data-screen="diary"] .dg-col .diary-col-h b { font-size: 14px; }
  /* cards: bigger, tappable, with a clear status rail; the ≥30-min line reads clean */
  [data-screen="diary"] .dg-ev { left: 5px; right: 3px; padding: 6px 10px; font-size: 12.5px; border-radius: 10px; }
  [data-screen="diary"] .dg-ev b { font-size: 12.5px; }
  [data-screen="diary"] .dg-ev .dg-ev-sub { font-size: 11px; }
  /* the current-time line reads brighter on the busy phone grid; its bleed
     matches the phone column gap (8px) so the rule stays continuous */
  [data-screen="diary"] .dg-now { border-top-width: 2px; }
  [data-screen="diary"] .dg-col:not(:last-child) .dg-lane .dg-now { right: -8px; }
}

/* ═══ PANEL P1-5: the voucher redeem form speaks the console's input language
   (it wears .diary-res-add, whose styles were diary-scoped) + 44px controls. ═══ */
[data-screen="vouchers"] .diary-res-add{display:flex;gap:8px;flex-wrap:wrap}
[data-screen="vouchers"] .diary-res-add input{font-family:var(--sans);font-size:14px;padding:9px 11px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--paper);color:var(--fg);min-height:44px}
[data-screen="vouchers"] .diary-res-add input[name="code"]{flex:1;min-width:200px}
[data-screen="vouchers"] .diary-res-add .btn{min-height:44px}

/* ═══ ANVUL HOURS PICKER (DRAG-HOURS, founder 2026-07-14: hours are dragged,
   never typed). ONE component, THREE mounts: the Booking-settings fold + the
   per-staff Hours fold here, and the signup wizard — which carries the SAME
   rules on its own tokens in web/onboarding/index.html <style>. Keep the two
   rule sets structurally in step. ═══ */
.ahp{ --ahp-acc:var(--signal-ink); --ahp-acc-text:var(--signal-deep);
      --ahp-line:var(--line-strong); --ahp-paper:var(--paper); --ahp-rail:var(--line-soft);
      --ahp-fg:var(--fg); --ahp-fg-soft:var(--fg-soft);
      font-size:13px; max-width:560px; }
.ahp-days{ display:flex; gap:5px; }
.ahp-day{ flex:1 1 0; min-width:0; min-height:46px; padding:5px 2px 4px; cursor:pointer;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
  font:inherit; font-weight:600; color:var(--ahp-fg-soft);
  background:var(--ahp-paper); border:1.5px solid var(--ahp-line); border-radius:10px;
  transition:background .12s, border-color .12s, color .12s; }
.ahp-day.on{ background:var(--ahp-acc); border-color:var(--ahp-acc); color:#fff; }
.ahp-day.focus{ box-shadow:0 0 0 2px var(--ahp-paper), 0 0 0 4px var(--ahp-acc); }
.ahp-day:focus-visible{ outline:2px solid var(--ahp-acc-text); outline-offset:2px; }
.ahp-dname{ font-size:12px; line-height:1.2; }
.ahp-dmini{ font-size:9.5px; line-height:1.1; font-weight:500; opacity:.92; white-space:nowrap; max-width:100%; overflow:hidden; }
.ahp-bar{ margin-top:14px; }
.ahp-bar.off{ opacity:.45; pointer-events:none; }
.ahp-lab{ text-align:center; font-weight:700; font-size:14px; color:var(--ahp-fg); font-variant-numeric:tabular-nums; min-height:20px; }
.ahp-track{ position:relative; height:44px; margin:0 12px; cursor:pointer; touch-action:none; }
.ahp-rail{ position:absolute; left:-6px; right:-6px; top:50%; height:8px; transform:translateY(-50%);
  background:var(--ahp-rail); border-radius:999px; }
.ahp-fill{ position:absolute; top:50%; height:8px; transform:translateY(-50%);
  background:var(--ahp-acc); border-radius:999px; }
.ahp-handle{ position:absolute; top:0; width:44px; height:44px; margin-left:-22px; z-index:2;
  display:flex; align-items:center; justify-content:center; cursor:grab; border-radius:50%;
  -webkit-tap-highlight-color:transparent; }
.ahp-handle:active{ cursor:grabbing; }
.ahp-knob{ width:22px; height:22px; border-radius:50%; background:var(--ahp-paper);
  border:3px solid var(--ahp-acc); box-shadow:0 1px 4px rgba(0,0,0,.22); pointer-events:none;
  transition:transform .1s; }
.ahp-handle:active .ahp-knob{ transform:scale(1.15); }
.ahp-handle:focus{ outline:none; }
.ahp-handle:focus-visible .ahp-knob,
.ahp-handle:focus .ahp-knob{ box-shadow:0 0 0 3px var(--ahp-paper), 0 0 0 5px var(--ahp-acc-text), 0 1px 4px rgba(0,0,0,.22); }
.ahp-scale{ display:flex; justify-content:space-between; margin:2px 6px 0; font-size:10px;
  color:var(--ahp-fg-soft); font-variant-numeric:tabular-nums; user-select:none; }
.ahp-same{ display:inline-flex; align-items:center; gap:7px; margin-top:10px; font-size:12.5px;
  font-weight:600; color:var(--ahp-fg); cursor:pointer; min-height:24px; }
.ahp-same input{ width:16px; height:16px; accent-color:var(--ahp-acc); cursor:pointer; }
.ahp-same input:focus-visible{ outline:2px solid var(--ahp-acc-text); outline-offset:2px; }
.ahp-hint{ margin:5px 0 0; font-size:11.5px; color:var(--ahp-fg-soft); min-height:15px; }

/* ═══ MEMBERS / HIRE / EVENTS — PHONE (the members screen had NO mobile CSS →
   each row's name + status pill + Pause/Cancel/Activate buttons crammed onto one
   line at 390px and overflowed). On a phone each list row stacks: the identity
   block on top, then the status + its actions wrap to a full-width action row
   below. Buttons grow to a tappable size and share the width. Applies to the
   members, hire and events list cards (they share the .row.between + actions
   shape). ═══ */
@media (max-width: 560px) {
  [data-screen="members"] #memMembersList .row.between,
  [data-screen="hire"] #hireBookingsList .row.between,
  [data-screen="events"] #evtList .card > .row.between {
    flex-direction: column; align-items: stretch; gap: 8px;
  }
  /* the status pill + action buttons sit on their own line, wrapping, and each
     button stretches to a comfortable share of the width */
  [data-screen="members"] #memMembersList .row.between > .row,
  [data-screen="hire"] #hireBookingsList .row.between > .row {
    justify-content: flex-start; flex-wrap: wrap; width: 100%;
  }
  [data-screen="members"] #memMembersList .row.between > .row .btn,
  [data-screen="hire"] #hireBookingsList .row.between > .row .btn {
    flex: 1 1 auto; min-height: 40px;
  }
  /* the plan/settings header buttons wrap instead of squeezing */
  [data-screen="members"] .mem-tabs #memSettingsBtn { margin-left: 0; }
  /* the settings + plan forms go full-width so the inputs aren't clipped */
  [data-screen="members"] #memSettings input,
  [data-screen="members"] #memSettings textarea { max-width: 100% !important; }
}

/* ═══════════════════════════════════════════════════════════════════════
   === U3 Diary/Reservations ===  (booking-engine ledger boards)
   THE SUM comes to the two booking screens. Money/covers wear the SHARED
   .sum / .sum-total primitives (fascia-ledger.css: mono tabular + the audited
   double-rule); this block is layout only — every colour is a brand token.
   Consumes: .sum, .sum-total, --mono, --line, --line-strong, --terra*.
   ═══════════════════════════════════════════════════════════════════════ */

/* ---- DIARY: THE SUM on the day grid ---- */
/* the per-booking figure inside a day-grid card — the clerk's mono, terracotta
   so the money reads first; "on quote" is a quiet muted note, never a number */
.dg-ev .dg-ev-sum { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 11px; color: var(--terra-text, #a8472b); font-weight: 600; letter-spacing: .01em; }
.dg-ev .dg-ev-sum::before { content: "· "; color: var(--ink-3, #857d70); font-weight: 400; }
.dg-ev .dg-ev-sum.dg-ev-sum--q { color: var(--ink-3, #857d70); font-weight: 500; }
/* on the tiniest cards the whole lockup is one clipped line already — the
   figure rides inline after the sub, so no extra rule needed there. */

/* the COLUMN foot — closes each resource column with its day total under the
   lane; the double-rule is the shared .sum-total, we add only the layout */
.dg-col-sum { display: flex; align-items: baseline; justify-content: flex-end; gap: 8px; margin-top: 10px; padding-top: 2px; }
.dg-col-sum .dg-col-sum-k { font-family: var(--mono); font-size: 9.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3, #857d70); }
.dg-col-sum .sum-total { font-size: 15px; font-weight: 650; color: var(--ink, #1c1b19); padding: 1px 1px 3px; line-height: 1.2; }
.dg-col-sum .dg-col-q { flex-basis: 100%; text-align: right; font-family: var(--mono); font-size: 10px; color: var(--ink-3, #857d70); margin-top: 3px; }

/* the DAY foot — the grand total under the whole grid; the "what's today
   worth" number the paper diary never had */
.dg-day-sum { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-top: 18px; padding: 14px 16px 12px; border: 1px solid var(--line, rgba(28,27,25,.12)); border-radius: 14px; background: var(--paper, #f4f2ec); }
.dg-day-sum.dg-day-sum--empty { justify-content: flex-start; padding: 12px 16px; }
.dg-day-sum .dg-day-sum-l { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dg-day-sum .dg-day-sum-k { font-family: var(--display, "Bricolage Grotesque", sans-serif); font-size: 15px; font-weight: 700; letter-spacing: -.01em; color: var(--ink, #1c1b19); }
.dg-day-sum .dg-day-sum-jobs { font-family: var(--mono); font-size: 11px; color: var(--ink-3, #857d70); letter-spacing: .02em; }
.dg-day-sum .dg-day-q { font-family: var(--mono); font-size: 11px; color: var(--terra-text, #a8472b); letter-spacing: .01em; }
.dg-day-sum .dg-day-sum-v.sum-total { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 26px; font-weight: 650; color: var(--ink, #1c1b19); letter-spacing: -.01em; display: inline-block; padding: 2px 2px 5px; line-height: 1.15; }

/* ---- RESERVATIONS: THE BOOK ---- */
/* the ledger header — the day, its fill (covers of capacity) as the audited
   .sum-total, the table count */
.resv-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.resv-head .resv-head-l { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.resv-head .resv-head-k { font-family: var(--display, "Bricolage Grotesque", sans-serif); font-size: 17px; font-weight: 700; letter-spacing: -.01em; color: var(--ink, #1c1b19); }
.resv-head .resv-head-sub { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3, #857d70); letter-spacing: .02em; }
.resv-head .resv-head-r { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.resv-head .resv-covers.sum-total { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 24px; font-weight: 650; color: var(--ink, #1c1b19); letter-spacing: -.01em; display: inline-block; padding: 2px 2px 5px; line-height: 1.15; }
.resv-head .resv-covers-k { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3, #857d70); }
/* OVER CAPACITY — the day's covers exceed its seats: the figure + note tint the
   block-red so an over-booked floor never reads deadpan ("31 / 30"). */
.resv-head .resv-covers.sum-total.is-over { color: var(--block, #b23b2e); }
.resv-head .resv-covers-k.is-over { color: var(--block, #b23b2e); font-weight: 700; }

/* a SERVICE PERIOD — Lunch / Evening (tables) or Morning/Afternoon/Evening
   (stays); a ledger of ruled rows closing with its covers subtotal. The head is
   CLAUSE-NUMBERED (01 / LUNCH) — F1's anvClause when present, else this fallback. */
.resv-period { margin-bottom: 16px; padding-top: 12px; padding-bottom: 12px; }
.resv-period .resv-period-h { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding-bottom: 8px; margin-bottom: 2px; border-bottom: 1px solid var(--line-strong, rgba(28,27,25,.20)); }
.resv-period .resv-period-hl { display: inline-flex; align-items: baseline; gap: 9px; min-width: 0; }
/* the mono clause number — a ruled "01" that opens the period like a ledger clause */
.resv-period .resv-period-no { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 11px; font-weight: 700; letter-spacing: .06em; color: var(--terra-text, #a8472b); padding: 1px 6px; border: 1px solid var(--line-strong, rgba(28,27,25,.20)); border-radius: 4px; flex: none; }
.resv-period .resv-period-name { font-family: var(--display, "Bricolage Grotesque", sans-serif); font-size: 14.5px; font-weight: 700; letter-spacing: .01em; color: var(--ink, #1c1b19); text-transform: uppercase; }
.resv-period .resv-period-sub { font-family: var(--mono); font-size: 11px; color: var(--ink-3, #857d70); letter-spacing: .02em; }
.resv-period .resv-period-sum { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-top: 8px; }
.resv-period .resv-period-sum-k { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3, #857d70); }
.resv-period .resv-period-sum .sum-total { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 15px; font-weight: 650; color: var(--ink, #1c1b19); padding: 1px 1px 3px; line-height: 1.2; }

/* ── A RESERVATION ROW = FLAT ruled-grid cells (Phase R1). The SAME cells serve
   two layouts. PHONE (≤719px, the audit's 8/10 — preserved to the pixel): a left
   mono TIME+PARTY rail, a right stack of name / room·status / contact / note /
   actions. DESKTOP (≥720px): a TRUE RULED LEDGER GRID —
     time | name | room | contact | note ·····leader····· ×party
   with hairline column rules and a dot-leader running to the right-hand covers
   (party) figure, so the old 60% desktop void becomes the Ruled Page. ── */
.resv-rows { display: flex; flex-direction: column; }
.resv-row {
  display: grid; grid-template-columns: 54px minmax(0, 1fr); column-gap: 12px; row-gap: 3px;
  padding: 11px 2px; border-top: 1px solid var(--line, rgba(28,27,25,.12)); align-items: baseline;
}
.resv-row:first-child { border-top: 0; }
/* the cells (phone placement — explicit so the empty contact/note collapse) */
.resv-row .rr-time  { grid-column: 1; grid-row: 1; font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 14px; font-weight: 650; color: var(--ink, #1c1b19); letter-spacing: -.01em; white-space: nowrap; }
.resv-row .rr-party { grid-column: 1; grid-row: 2; align-self: start; font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; font-size: 12px; font-weight: 600; color: var(--terra-text, #a8472b); white-space: nowrap; }
.resv-row .rr-name  { grid-column: 2; grid-row: 1; min-width: 0; }
.resv-row .rr-name b { font-size: 14px; font-weight: 650; color: var(--ink, #1c1b19); }
.resv-row .rr-room  { grid-column: 2; grid-row: 2; font-family: var(--mono); font-size: 11px; color: var(--ink-3, #857d70); letter-spacing: .02em; min-width: 0; }
.resv-row .rr-contact { grid-column: 2; grid-row: 3; font-size: 12.5px; min-width: 0; }
.resv-row .rr-contact a { font-family: var(--mono); color: var(--terra-text, #a8472b); text-decoration: none; letter-spacing: .01em; }
.resv-row .rr-contact a:hover { text-decoration: underline; }
.resv-row .rr-note  { grid-column: 2; grid-row: 4; font-size: 12.5px; color: var(--ink-2, #5d574c); font-style: italic; min-width: 0; }
.resv-row .resv-row-acts { grid-column: 1 / -1; grid-row: 5; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; align-items: center; }
/* on a phone an empty contact/note cell collapses (no ghost gap) */
@media (max-width: 719.98px) {
  .resv-row .rr-contact:empty, .resv-row .rr-note:empty { display: none; }
}
/* a cancelled / no-showed booking reads struck-through and dimmed */
.resv-row.diary-cancelled, .resv-row.diary-no_show { opacity: .6; }
.resv-row.diary-cancelled .rr-name b, .resv-row.diary-no_show .rr-name b,
.resv-row.diary-cancelled .rr-time, .resv-row.diary-no_show .rr-time { text-decoration: line-through; }
.resv-row.diary-completed .rr-room { color: var(--ok, #2f7d57); }

/* ── DESKTOP RULED GRID (≥720px) — rule the span: the row becomes one ledger line
   of aligned columns with hairline column rules; the party rides the far right as
   the covers figure with a dotted LEADER running to it. Actions drop to a quiet
   full-width second line so the data line stays a clean ruled row. ── */
@media (min-width: 720px) {
  .resv-row {
    grid-template-columns:
      62px                     /* time  */
      minmax(150px, 1.5fr)     /* name  */
      minmax(110px, 1fr)       /* room  */
      minmax(120px, 1.1fr)     /* contact */
      minmax(60px, 1.7fr)      /* note + leader */
      auto;                    /* party (covers) */
    column-gap: 0; row-gap: 0; align-items: baseline;
  }
  .resv-row .rr-time  { grid-column: 1; grid-row: 1; padding: 0 14px 0 0; }
  .resv-row .rr-name  { grid-column: 2; grid-row: 1; padding: 0 14px; border-left: 1px solid var(--line, rgba(28,27,25,.10)); }
  .resv-row .rr-room  { grid-column: 3; grid-row: 1; padding: 0 14px; border-left: 1px solid var(--line, rgba(28,27,25,.10)); font-size: 12px; }
  .resv-row .rr-contact { grid-column: 4; grid-row: 1; padding: 0 14px; border-left: 1px solid var(--line, rgba(28,27,25,.10)); }
  .resv-row .rr-note  { grid-column: 5; grid-row: 1; padding: 0 8px 0 14px; border-left: 1px solid var(--line, rgba(28,27,25,.10)); display: flex; align-items: baseline; min-width: 0; }
  /* the DOT-LEADER — runs from the note text to the covers figure on the right */
  .resv-row .rr-note::after { content: ""; flex: 1 1 auto; min-width: 18px; margin: 0 2px 4px 8px; border-bottom: 1px dotted var(--line-strong, rgba(28,27,25,.28)); }
  .resv-row .rr-note:empty { justify-content: flex-end; }
  .resv-row .rr-note:empty::after { margin-left: 0; }
  /* the right-hand COVERS figure — the ×party the leader points to */
  .resv-row .rr-party { grid-column: 6; grid-row: 1; padding: 0 2px 0 14px; text-align: right; align-self: baseline; font-size: 13px; border-left: 1px solid var(--line, rgba(28,27,25,.10)); }
  .resv-row .resv-row-acts { grid-column: 1 / -1; grid-row: 2; margin-top: 8px; padding-top: 0; }
}

@media (max-width: 480px) {
  .dg-day-sum, .resv-head { gap: 10px; }
  .dg-day-sum .dg-day-sum-v.sum-total, .resv-head .resv-covers.sum-total { font-size: 22px; }
  .resv-row { grid-template-columns: 52px minmax(0, 1fr); column-gap: 10px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   === U3 Orders/Members/Hire ===  (money-heavy engine ledger boards)
   THE headline ledger board comes to the three money engines. Money wears the
   SHARED .sum / .sum-total (fascia-ledger.css: mono tabular + the audited
   double-rule); the stat ribbons use the SHARED .stat-row / .stat-cell. This
   block is layout only — every colour is a brand token (--signal terracotta,
   --warn amber, --block red, --ok green).
   ═══════════════════════════════════════════════════════════════════════ */

/* ORDERS — the "Today's takings" ribbon sits over the board, like a till roll's
   header. Just spacing; the ribbon itself is the shared .stat-row. "Taken today"
   carries total:true → the SUM double-rule (F1's anvStatRow upgrade). */
.ord-takings { margin: 0 0 14px; }
/* 390 RIBBON FIX: the shared .stat-cell drops to 40% basis ≤560 (2-up), which
   orphan-wraps the 3rd cell (2+1) and, with a money cell, pushes the timestamp
   under the total. On the 3-cell TAKINGS ribbon force a 3-up single line: ~33%
   basis, no min-width fight, and let the mono figure shrink to hold the line. */
.ord-takings.stat-row { flex-wrap: nowrap; }
.ord-takings .stat-cell { min-width: 0; flex: 1 1 0; padding: 14px 12px; }
.ord-takings .stat-cell .stat-v { font-variant-numeric: tabular-nums lining-nums; }
@media (max-width: 560px) {
  .ord-takings .stat-cell { min-width: 0; flex-basis: 0; padding: 13px 9px; }
  .ord-takings .stat-cell .stat-v { font-size: 21px; }
  .ord-takings .stat-cell .stat-v.sum { font-size: 18px; letter-spacing: -0.02em; }
  .ord-takings .stat-k { font-size: 9px; letter-spacing: 0.05em; }
}

/* ── ORDERS TILL-ROLL PARTITION (R1 P0). The flat 6,400px stream becomes ruled,
   clause-numbered sections (01/NEW · 02/IN PROGRESS · 03/READY & DISPATCHED ·
   04/SETTLED[folded]) — each with a per-group £ TAKEN sum (paid money only). At
   ≥1100px the sections compose into TWO ledger columns (live queue | fulfilment),
   killing the desktop single-column scroll; below that they stack in reading
   order. Layout only; the clause head is F1's shared .clause-head. ── */
.ord-group { margin: 0 0 18px; }
.ord-group:last-child { margin-bottom: 0; }
/* the group's cards + its £ sum ride under the clause head */
.ord-group-body { margin-top: 10px; }
/* a NEW group holding a late-to-confirm order flags its head amber (the same
   nudge the ribbon's "Late" cell carries) */
.ord-group.is-flagged .clause-head .clause-no { color: var(--warn); }
.ord-group.is-flagged .clause-head { border-bottom-color: var(--warn-line); }
/* the per-group TAKEN sum — right-aligned, the audited .sum-total double-rule,
   matching the hire-group-sum voice so both money boards read the same */
.ord-group-sum {
  display: flex; align-items: baseline; justify-content: flex-end; gap: 12px;
  margin-top: 4px; padding-top: 10px; border-top: 1px solid var(--line);
}
.ord-group-sum .ord-group-sum-k {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint);
}
.ord-group-sum .sum-total { font-size: 15px; font-weight: 650; }
/* SETTLED folds behind its count (history shouldn't crowd the live queue) — the
   clause head doubles as the fold toggle, a quiet full-width button. */
.ord-group--settled .ord-fold-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: transparent; border: 0; padding: 0; cursor: pointer; text-align: left;
  -webkit-appearance: none; appearance: none; font: inherit; color: inherit;
}
.ord-group--settled .ord-fold-toggle .clause-head { flex: 1 1 auto; margin: 0; }
.ord-group--settled .ord-fold-chev { flex: none; color: var(--fg-faint); display: inline-flex; transition: transform .18s ease; }
.ord-group--settled.is-open .ord-fold-chev { transform: rotate(180deg); }
.ord-group--settled .ord-fold-toggle:hover .clause-label { color: var(--fg); }
.ord-group--settled .ord-fold-toggle:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; border-radius: 4px; }
.ord-group--settled .ord-group-body { margin-top: 12px; }
/* the two ledger columns — desktop composition */
.ord-board-cols { display: block; }
@media (min-width: 1100px) {
  .ord-board-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; align-items: start; }
  .ord-col { min-width: 0; }
}
/* the WALL-course end-stop under the last group — spacing only (the brick is
   F1's .wall-course primitive); scoped so it can't clash with F1's own rule */
[data-screen="orders"] .board-close { margin: 6px 0 2px; }

/* MEMBERS — "THE BOOK" ribbon (Active/New/Paused/Payment-due + the standing
   monthly value in .sum .sum-total). Spacing only; the money cell already wears
   the audited rule. */
.mem-book { margin: 0 0 16px; }
/* the arrears cell reads its figure in the block-red like the desk's alarm rows
   (mem-book's Payment-due carries tone "block" → .is-block already colours the
   figure; this keeps the whole cell legible when the count is 0 vs live). */
.mem-book .stat-cell.is-block .stat-v { color: var(--block); }

/* ── MEMBERS ROSTER = A LEDGER (R1). The prose "Name — plan · £35/mo … [pill]"
   row becomes a three-part ruled row: the member (name + meta) | a right-aligned
   mono STANDING-£ column (≥560px) | the status pill + actions. Below 560 the
   figure rides inline in the meta (.mem-inline-price) — a phone has no room for a
   column; ≥560 that inline copy hides and the column carries the money so the
   book reads as a ledger. The roster closes on a double-ruled BOOK TOTAL that
   reconciles with the ribbon. ── */
.mem-roster .mem-row {
  display: flex; gap: 12px; align-items: baseline;
  padding: 10px 0; border-top: 1px solid var(--line);
}
.mem-roster .mem-row:first-child { border-top: 0; }
.mem-roster .mem-row-main { flex: 1 1 auto; min-width: 0; }
.mem-roster .mem-row-main b { font-size: 14.5px; font-weight: 650; color: var(--fg); }
/* the standing-£ ledger column — mono, tabular, right-aligned; a fixed rail so the
   figures line up down the page (a true ledger column). Hidden on a phone. */
.mem-roster .mem-row-fig {
  display: none; flex: none; width: 108px; text-align: right;
  font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums;
  font-size: 14px; font-weight: 650; color: var(--fg); letter-spacing: -0.005em;
  align-self: center; white-space: nowrap;
}
.mem-roster .mem-row-fig .mem-row-fig-p { font-size: 11px; font-weight: 600; color: var(--fg-faint); margin-left: 1px; }
.mem-roster .mem-row-fig.is-empty { color: var(--fg-faint); }
/* money AT RISK — a failed card reads amber and struck; surfaced, never erased */
.mem-roster .mem-row-fig.is-arrears { color: var(--warn); text-decoration: line-through; text-decoration-color: var(--warn-line); }
.mem-roster .mem-row-fig.is-arrears .mem-row-fig-p { color: var(--warn); }
.mem-roster .mem-row-side { display: flex; gap: 8px; flex: none; align-items: center; }
.mem-inline-price { font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums; }
@media (min-width: 560px) {
  .mem-roster .mem-row-fig { display: block; }
  .mem-roster .mem-inline-price { display: none; }  /* the column carries it now */
}
/* the BOOK TOTAL foot — the roster's double-rule, right-aligned, reconciling with
   the ribbon's "if all active pay". The .sum-total gives the audited double-rule. */
.mem-book-foot {
  display: flex; align-items: baseline; justify-content: flex-end; gap: 14px;
  margin-top: 12px; padding-top: 12px; border-top: 1.5px solid var(--line-strong);
}
.mem-book-foot .mem-foot-k {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint);
}
.mem-book-foot .mem-foot-fig { text-align: right; }
.mem-book-foot .mem-foot-fig .sum-total { font-size: 17px; font-weight: 650; }
.mem-book-foot .mem-foot-p { font-size: 11px; font-weight: 600; color: var(--fg-faint); margin-left: 1px; }
/* the arrears line under the total — amber, mono, the money-at-risk restated */
.mem-book-foot .mem-foot-arrears {
  font-family: var(--mono); font-variant-numeric: tabular-nums lining-nums;
  font-size: 11.5px; font-weight: 600; color: var(--warn); margin-top: 3px;
}

/* ── MEMBERS PLANS — the per-plan STANDING line: "24 × £35/mo = £840/mo" set in
   the clerk's mono, the total on the audited double-rule. A book value the firm
   can read at a glance. ── */
.mem-plan-standing {
  display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  margin-top: 7px; font-family: var(--mono);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 12.5px; color: var(--fg-soft);
}
.mem-plan-standing .mem-plan-standing-x,
.mem-plan-standing .mem-plan-standing-eq { color: var(--fg-faint); font-weight: 600; }
.mem-plan-standing .sum-total { font-size: 13.5px; font-weight: 650; color: var(--fg); padding: 0; }

/* ── MEMBERS PLAN EDITOR — the fields carried browser-default chrome + stretched
   full-card at 1440 (field sprawl). Give the members form the same ruled input
   language every other console form wears, and cap the free-text fields so the
   editor reads composed, not a wall of full-width inputs. (Widths are also set
   inline on each input as a load-order belt-and-braces.) ── */
[data-screen="members"] .diary-res-add input,
[data-screen="members"] .diary-res-add select,
[data-screen="members"] .diary-res-add textarea {
  font-family: var(--sans); font-size: 13.5px; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--paper); color: var(--fg);
}
[data-screen="members"] .mem-plan-form input[name="name"] { max-width: 340px; }
[data-screen="members"] .mem-plan-form input[name="perks"] { max-width: 520px; }
[data-screen="members"] .mem-plan-form .mem-plan-period {
  -webkit-appearance: none; appearance: none; padding-right: 30px; min-width: 130px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23857d70' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}

/* HIRE — the TIME-TRUE ledger board: NUMBERED clause group heads (F1's
   .clause-head, "01 / OVERDUE  2"), the fascia date range, deposit STATE pills
   with the level-bubble true-mark, per-row actions demoted to a QUIET rail (the
   entry outranks the buttons — R1), and a summed-deposit footer per group. */
.hire-group { margin: 0 0 18px; }
.hire-group:last-child { margin-bottom: 0; }
/* the clause head opens each group; spacing under it before the card of rows */
.hire-group--clause .clause-head { margin-bottom: 10px; }
/* the OVERDUE group is struck in the block-red — the desk's alarm section. The
   clause number + label + rule go red; the rows' card takes the alarm ground. */
.hire-group--clause.is-overdue .clause-head { border-bottom-color: var(--block-line); }
.hire-group--clause.is-overdue .clause-head .clause-no,
.hire-group--clause.is-overdue .clause-head .clause-label { color: var(--block); }
.hire-group--clause.is-overdue .clause-head .clause-extra { color: var(--block); }
.hire-group.is-overdue .hire-group-body { border-color: var(--block-line); background: var(--block-soft); }

/* ── ONE HIRE ROW = ENTRY | RAIL. The ENTRY (item · date range · customer) is the
   widest, primary thing; the deposit + status pills and the ACTIONS sit in a
   quiet right rail. Desktop: rail floats right, actions under the pills. Phone:
   the rail drops under the entry but the actions stay SMALL (never full-width
   Cancel bars) — the R1 "entries outrank the buttons". ── */
.hire-row {
  display: flex; gap: 12px 16px; align-items: flex-start; flex-wrap: wrap;
  padding: 12px 0; border-top: 1px solid var(--line);
}
.hire-group-body > .hire-row:first-child { border-top: 0; padding-top: 2px; }
.hire-entry { flex: 1 1 260px; min-width: 0; }
.hire-rail { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 8px; margin-left: auto; }
.hire-pills { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; align-items: center; }
/* the QUIET action rail — small buttons, never full-width. The advance is a
   signal-tinted quiet button (present but not shouting over the entry); cancel is
   the faintest. Capped width so a rail item can't stretch into a bar. */
.hire-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.hire-actions .btn { flex: 0 0 auto; min-height: 30px; padding: 5px 12px; font-size: 12.5px; }
.hire-adv {
  background: var(--signal-soft); border: 1px solid var(--signal-line); color: #a8480f;
  box-shadow: none;
}
.hire-adv:hover { background: var(--signal-soft); border-color: var(--signal); color: #8f3d0d; }
.hire-cancel { color: var(--fg-faint); }
.hire-cancel:hover { color: var(--fg-soft); }
/* the DATE RANGE — fascia-size mono, tabular; the defining visual of a hire */
.hire-range {
  font-family: var(--mono); font-size: 13.5px; font-weight: 650;
  letter-spacing: 0.01em; white-space: nowrap; color: var(--fg);
  font-variant-numeric: tabular-nums lining-nums;
}
.hire-range.is-over { color: var(--block); }
/* the "N days over" tell on an overdue hire's range */
.hire-over {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--block);
  margin-left: 6px; white-space: nowrap;
}
/* an overdue row gets a red left-edge so it reads as urgent at a glance */
.hire-row.is-over { box-shadow: inset 3px 0 0 var(--block); padding-left: 8px; }
/* the deposit STATE pill inherits .pill / .pill.ok; keep its figure mono+tabular */
.hire-dep { font-variant-numeric: tabular-nums lining-nums; }

/* THE LEVEL-BUBBLE true-mark — a drawn dot-centred-in-lines glyph (spirit level
   reading true) marking a VERIFIED money state (a real card hold / a completed
   refund). Shared primitive (.level-dot); sits inside the .pill.ok deposit pill
   in place of the generic dot. NOT an emoji — an inline SVG that inherits colour.*/
.level-dot { display: inline-flex; align-items: center; justify-content: center; margin-right: 4px; flex: none; line-height: 0; }
.level-dot svg { display: block; }
.pill.ok .level-dot { color: var(--ok-ink, #1d7a4d); opacity: .9; }

/* HIRE ITEMS pane — the meta line's figures (rates, deposit, qty, on-hire) read
   as tabular ledger numerals so they align, without forcing the prose to mono. */
.hire-item-meta { font-variant-numeric: tabular-nums lining-nums; }

/* the summed-deposit footer — right-aligned, the audited .sum-total rule */
.hire-group-sum {
  display: flex; align-items: baseline; justify-content: flex-end; gap: 12px;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
}
.hire-group-sum-k {
  font-family: var(--mono); font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--fg-faint);
}
.hire-group-sum .sum-total { font-size: 15px; font-weight: 650; }
/* the WALL-course end-stop under the last group — spacing only (F1's .wall-course
   brick); scoped so it can't clash with F1's own .board-close rule */
[data-screen="hire"] .board-close { margin: 6px 0 2px; }

/* MOBILE (≤560px): the U2 audit's members-plans-pane gap — the earlier fix only
   reached #memMembersList, leaving the PLANS pane cramped. Cover it here (its
   cards share the .card > .row.between + actions shape), and let the hire deposit
   pill wrap onto its own line with the status pill on a phone. */
@media (max-width: 560px) {
  [data-screen="members"] #memPlansList .card > .row.between {
    flex-direction: column; align-items: stretch; gap: 8px;
  }
  [data-screen="members"] #memPlansList .card > .row.between > .row {
    justify-content: flex-start; flex-wrap: wrap; width: 100%;
  }
  [data-screen="members"] #memPlansList .card > .row.between > .row .btn {
    flex: 1 1 auto; min-height: 40px;
  }
  /* the plan editor's inputs go full-width so nothing is clipped */
  [data-screen="members"] #memPlanEditor input,
  [data-screen="members"] #memPlanEditor select { max-width: 100% !important; }
  /* HIRE ≤560: the rail drops UNDER the entry, left-aligned, and the quiet actions
     stay SMALL (never full-width Cancel bars — the entry is the widest thing). */
  .hire-group--clause .clause-head { padding-bottom: 6px; }
  .hire-rail { align-items: flex-start; width: 100%; margin-left: 0; }
  .hire-pills { justify-content: flex-start; }
  .hire-actions { justify-content: flex-start; }
  /* guard: even if a global mobile rule stretches .card buttons, the hire rail's
     buttons stay compact so they can't become full-width bars. */
  [data-screen="hire"] #hireBookingsList .hire-actions .btn { flex: 0 0 auto; width: auto; min-height: 32px; }
}

