/* ================================================================
   design.css — SERVORA design system (the single source of truth).
   Aesthetic: "Professional Trade meets modern SaaS" — deep blue, crisp
   white cards on a cool-clean canvas, soft layered shadows, confident
   Inter type, tabular numbers for money. Calm, trustworthy, premium.
   Every class hook below is used across the contractor console, client
   portal, subcontractor portal, command center, and marketing site.

   Fonts (Inter) load via a <link> in each page's <head>:
     <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
   ================================================================ */

:root{
  /* COLOR — one loud accent (Servora deep blue). Cool-neutral canvas. */
  --ink:#101828;            /* headlines, primary text (blue-black) */
  --ink-2:#1D2939;          /* slightly softer heading ink */
  --slate:#667085;          /* secondary text */
  --slate-2:#98A2B3;        /* decoration ONLY (borders, dividers, the select chevron).
                                At 2.6:1 on white it fails AA for text; anything a person
                                has to read (placeholders, day-of-week headers, group
                                labels, counts) uses --slate or --slate-3, never this. */
  --slate-3:#5A6474;        /* darker tertiary text, ~6:1 on white — for the small
                                uppercase/informational text that used to sit on --slate-2 */
  --paper:#F5F7FB;          /* cool off-white page bg */
  --paper-2:#EEF2F8;        /* recessed surfaces */
  --card:#FFFFFF;
  --line:#E6EAF0;           /* hairline borders */
  --line-2:#EEF1F6;         /* subtle inner dividers */

  --accent:#1D4ED8;         /* SERVORA deep blue — primary action / active */
  --accent-2:#2E6BF0;       /* lighter stop for gradients */
  --accent-ink:#1A3FB0;     /* hover / pressed */
  --accent-tint:#EAF1FE;    /* accent wash for bars/badges/tints */
  --accent-glow:rgba(29,78,216,.16);   /* soft halo behind the focus ring */
  --focus-ring:#1D4ED8;     /* the focus ring itself: 6.7:1 on white/paper only,
                                where it meets 1.4.11; the dark and amber surfaces
                                re-point this token per container (see the focus
                                block below) */
  --grad-accent:linear-gradient(180deg,var(--accent-2),var(--accent));

  --on-ink:#C3C9D4;         /* muted text/icons on dark (--ink) surfaces */
  --on-accent:#FFFFFF;      /* text/icon ON the accent (contrast-guarded on client portal) */

  --ok:#12A150;  --ok-tint:#E7F6EC;  --ok-ink:#0E5A2E;      /* paid / signed / done */
  --alert:#E5484D; --alert-tint:#FDECEC; --alert-ink:#B42318;/* needs-you: unpaid / unsigned / overdue */
  --warn:#D9820A;  --warn-tint:#FBF0DC; --warn-ink:#7A5A12;  /* pending / waiting */
  --neutral-tint:#EEF1F6;
  /* the -ink tokens are TEXT colours for the matching -tint background (chips, calendar
     chips, demo/folder badges): --ok/--alert/--warn on their own tint only clear 2.6-3.4:1
     and fail AA for the small chip text that used to sit directly on them. Keep
     --ok/--alert/--warn as-is for solid fills (white text on them, e.g. .ds-btn--danger),
     where the contrast was already fine. */

  /* TYPE */
  --font-display:"Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-ui:"Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* SPACE (8px grid) */
  --s1:4px; --s2:8px; --s3:16px; --s4:24px; --s5:32px; --s6:48px; --s7:64px;

  /* SHAPE — a small radius scale */
  --r-sm:8px; --radius:12px; --r-lg:16px; --r-xl:22px; --r-pill:999px;

  /* DEPTH — soft, layered, low-opacity (the modern floating-card look) */
  --shadow-xs:0 1px 2px rgba(16,24,40,.05);
  --shadow-sm:0 1px 2px rgba(16,24,40,.06),0 1px 3px rgba(16,24,40,.05);
  --shadow-md:0 2px 6px -2px rgba(16,24,40,.08),0 8px 18px -6px rgba(16,24,40,.12);
  --shadow-lg:0 4px 10px -4px rgba(16,24,40,.10),0 20px 40px -12px rgba(16,24,40,.20);
  --shadow-accent:0 6px 18px -6px rgba(29,78,216,.45);
  --shadow:var(--shadow-sm);            /* back-compat alias */

  --topbar-h:58px;                      /* the topbar's real min-height, published so
                                            .fs-crumbs and .fs__side can track it instead of
                                            hardcoding the number twice; redefined to 52px in
                                            the <=640px block below to match the topbar there */
  --tap:48px;                           /* min tap target */
  --ease:cubic-bezier(.4,0,.2,1);
}

/* ---- base ---- */
*{box-sizing:border-box}
html,body{margin:0;padding:0;overflow-x:clip}
html{-webkit-text-size-adjust:100%}
body{
  font-family:var(--font-ui);
  font-size:16px; line-height:1.55;
  color:var(--ink); background:var(--paper);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  font-feature-settings:"cv05" 1,"ss01" 1;
}
::selection{background:var(--accent);color:#fff}
h1,h2,h3,.display{font-family:var(--font-display);font-weight:800;line-height:1.12;letter-spacing:-.018em;color:var(--ink);margin:0 0 var(--s2)}
h1{font-size:1.55rem}
h2{font-size:1.28rem;letter-spacing:-.015em}
h3{font-size:1.05rem;font-weight:700;letter-spacing:-.01em}
p{margin:0 0 var(--s3)}
a{color:var(--accent);text-decoration:none;transition:color .15s var(--ease)}
a:hover{color:var(--accent-ink)}
.u-slate{color:var(--slate)}
.u-mono-num{font-variant-numeric:tabular-nums;font-weight:600;letter-spacing:-.01em}
.u-center{text-align:center}
small{font-size:.8rem;color:var(--slate)}
hr{border:none;border-top:1px solid var(--line);margin:var(--s4) 0}

/* keyboard focus — visible, on-brand, never on mouse click
   ---------------------------------------------------------------------------
   THIS IS THE ONLY FOCUS STYLE IN THE CODEBASE, and it used to be
     outline:none; box-shadow:0 0 0 3px var(--accent-glow)
   which failed twice over.

   1. It was silently defeated. :focus-visible has specificity (0,1,0), the same
      as a plain class, and EVERY component later in this file that sets its own
      box-shadow therefore overwrote the ring: .ds-btn, .fs-tile, .ds-card--tap,
      .ds-seg button, .ds-kanban__card, .svc-kb__card, .mk-svc-card, .mk-door,
      .mk-nav__toggle, .svc-cal__btn. The `outline:none` still applied, so those
      controls had NO focus indicator at all. Keyboard users lost their place on
      every button in the app.
   2. Where it did render it was invisible anyway: --accent-glow is 16% alpha,
      about #DBE3F9 over white, roughly 1.3:1. WCAG 1.4.11 wants 3:1.

   outline is the right property: nothing else in this file declares it, so no
   component can clobber it, it is painted outside the border box so it does not
   disturb any component's resting shadow, and unlike box-shadow it survives
   forced-colors mode. The glow is kept as a soft halo but is no longer the
   signal. */
:focus-visible{outline:2px solid var(--focus-ring);outline-offset:2px;
  box-shadow:0 0 0 5px var(--accent-glow);border-radius:var(--r-sm)}
/* An outline is still clipped by an ancestor overflow:hidden, so rows that live
   inside a clipping container draw their ring inside themselves instead. */
.fs-file:focus-visible,.ds-table tr.tap:focus-visible,.ds-kanban__card:focus-visible{outline-offset:-3px}
/* One ring colour, drawn on five surfaces this file paints dark or amber.
   #1D4ED8 measures 2.65:1 on --ink (.ds-demo-bar, .mk-dark), 2.75:1 and 2.82:1
   on the two stops of the .hero4 gradient, 2.87:1 on .hero3, and 2.28:1 on
   --warn (.ds-assist-bar) - every one under the 3:1 floor of WCAG 1.4.11. The
   --accent-glow halo does not rescue them, it makes them worse: it tints the
   pixels on both sides of the ring, and over --ink that composite drops the
   ring to 2.36:1. Re-pointing the token per container keeps ONE ring style and
   ONE variable. White is 17.7:1 to 19.3:1 on the four navy surfaces; white on
   the amber assist bar would be only 2.94:1, so that one takes --ink at 6.04:1.
   Scoped to the CTA/cue wrappers inside the heroes, not the whole hero, because
   .mk-window and .mk-phone__screen nest inside .hero4__art / .hero3__art on a
   white background: a hero-wide white ring would be invisible if a focusable
   ever lands in one of those device mocks. Deliberately NOT extended to
   .mk-nav.on-hero, which fails the same way (~2.79:1) but contains the white
   .mk-nav__panel mobile menu; that surface needs its own paired override. */
.ds-demo-bar,.mk-dark,.hero3__cta,.hero4__cta,.hero4__cue{--focus-ring:#FFFFFF}
.ds-assist-bar{--focus-ring:var(--ink)}

/* subtle custom scrollbars (desktop) */
@media(pointer:fine){
  *{scrollbar-width:thin;scrollbar-color:#CBD2DE transparent}
  *::-webkit-scrollbar{width:10px;height:10px}
  *::-webkit-scrollbar-thumb{background:#CBD2DE;border-radius:8px;border:3px solid transparent;background-clip:content-box}
  *::-webkit-scrollbar-thumb:hover{background:#AEB7C6;background-clip:content-box}
}

/* ---- layout helpers ---- */
.ds-wrap{max-width:1000px;margin:0 auto;padding:var(--s4) var(--s3)}
.ds-narrow{max-width:440px;margin:0 auto;padding:var(--s5) var(--s3)}
.ds-stack>*+*{margin-top:var(--s3)}
.ds-row{display:flex;align-items:center;justify-content:space-between;gap:var(--s3)}

/* ================================================================
   CORE COMPONENTS
   ================================================================ */

/* BUTTON — gradient primary with accent glow + tactile press. */
.ds-btn{
  --btn-bg:var(--grad-accent); --btn-fg:var(--on-accent); --btn-bd:transparent; --btn-sh:var(--shadow-accent);
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  min-height:var(--tap);padding:0 var(--s4);
  font-family:var(--font-ui);font-size:15px;font-weight:600;line-height:1;letter-spacing:-.01em;
  color:var(--btn-fg);background:var(--btn-bg);border:1px solid var(--btn-bd);
  border-radius:var(--radius);cursor:pointer;text-align:center;white-space:nowrap;
  box-shadow:var(--btn-sh);
  transition:transform .12s var(--ease),box-shadow .15s var(--ease),background .15s var(--ease),opacity .15s;
}
.ds-btn:hover{transform:translateY(-1px);--btn-sh:0 8px 22px -6px rgba(29,78,216,.5)}
.ds-btn:active{transform:translateY(0);--btn-sh:0 2px 8px -3px rgba(29,78,216,.5)}
/* Element-level opacity used to compound with the gradient background and white
   label, dropping the label to ~1.2:1 — the one time someone needs to read what a
   button says (a request in flight, a gated action) it became unreadable. Setting
   the disabled colours explicitly keeps the label at ~5.6:1 while the flat grey
   still reads as inactive. */
.ds-btn:disabled,.ds-btn[aria-disabled="true"]{--btn-bg:#D8DEE9;--btn-fg:#4A5568;--btn-bd:var(--line);--btn-sh:none;cursor:not-allowed;transform:none}
.ds-btn--secondary{--btn-bg:#fff;--btn-fg:var(--ink);--btn-bd:var(--line);--btn-sh:var(--shadow-xs)}
.ds-btn--secondary:hover{--btn-bg:#fff;--btn-bd:var(--slate-2);--btn-sh:var(--shadow-sm)}
.ds-btn--quiet{--btn-bg:transparent;--btn-fg:var(--accent);--btn-bd:transparent;--btn-sh:none;padding:0 var(--s2)}
.ds-btn--quiet:hover{--btn-bg:var(--accent-tint);--btn-fg:var(--accent-ink);transform:none}
/* Ghost used to exist only as a copy pasted separately into each dark hero
   (.hero3__cta, .hero4__cta); any other page reaching for
   class="ds-btn ds-btn--ghost" fell through to nothing and rendered as the
   default filled gradient with its blue accent shadow instead of a
   transparent button - the "looks like the primary button" bug seen on
   /services/consulting. currentColor lets a section with white text (or any
   other on-dark section) keep working without its own override, and
   --btn-sh:none drops the accent glow a transparent button should never carry. */
.ds-btn--ghost{--btn-bg:transparent;--btn-fg:currentColor;--btn-bd:rgba(255,255,255,.38);--btn-sh:none}
.ds-btn--block{width:100%}
.ds-btn--sm{min-height:38px;font-size:13.5px;padding:0 var(--s3);border-radius:var(--r-sm)}
.ds-btn--lock{--btn-bg:#EEF1F6;--btn-fg:var(--slate);--btn-bd:var(--line);--btn-sh:none;cursor:not-allowed}
.ds-btn--lock:hover{--btn-bg:#EEF1F6;transform:none}
.ds-btn--quiet.u-danger{color:var(--alert-ink)}
.ds-btn--danger{--btn-bg:var(--alert);--btn-sh:0 6px 18px -6px rgba(229,72,77,.45)}
.ds-btn--success{--btn-bg:var(--ok);--btn-sh:0 6px 18px -6px rgba(18,161,80,.45)}

.ds-spinner{width:17px;height:17px;border:2.5px solid rgba(255,255,255,.45);
  border-top-color:#fff;border-radius:50%;animation:ds-spin .7s linear infinite;display:inline-block}
.ds-btn--secondary .ds-spinner{border-color:rgba(16,24,40,.25);border-top-color:var(--ink)}
@keyframes ds-spin{to{transform:rotate(360deg)}}

/* STATUS CHIP — pill, icon + word + color (never color alone). */
.ds-chip{display:inline-flex;align-items:center;gap:5px;
  font-size:11.5px;font-weight:600;line-height:1;padding:5px 10px;
  border-radius:var(--r-pill);white-space:nowrap;letter-spacing:.01em}
.ds-chip .ds-chip__ico{font-size:12px;line-height:1;margin-top:-1px}
.ds-chip--ok{background:var(--ok-tint);color:var(--ok-ink)}
.ds-chip--alert{background:var(--alert-tint);color:var(--alert-ink)}
.ds-chip--warn{background:var(--warn-tint);color:var(--warn-ink)}
.ds-chip--accent{background:var(--accent-tint);color:var(--accent-ink)}
.ds-chip--neutral{background:var(--neutral-tint);color:var(--slate-3)}

/* CARD — white, soft shadow, generous radius. Tap cards lift on hover. */
.ds-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s4);box-shadow:var(--shadow-sm)}
.ds-card+.ds-card{margin-top:var(--s3)}
.ds-card--raised{box-shadow:var(--shadow-md)}
.ds-card--tap{cursor:pointer;transition:transform .14s var(--ease),box-shadow .18s var(--ease),border-color .18s}
.ds-card--tap:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:#DBE1EA}
.ds-card--tap:active{transform:translateY(0)}

/* INPUT — soft, focus glow ring. */
.ds-field{margin-bottom:var(--s3)}
.ds-label{display:block;font-weight:600;font-size:13.5px;margin-bottom:6px;color:var(--ink-2);letter-spacing:-.005em}
.ds-input,.ds-select,.ds-textarea{
  width:100%;min-height:var(--tap);padding:0 var(--s3);
  font-family:var(--font-ui);font-size:15px;color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:var(--radius);
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease)}
.ds-input::placeholder,.ds-textarea::placeholder{color:var(--slate)}
.ds-textarea{min-height:112px;padding:var(--s3);resize:vertical;line-height:1.55}
.ds-select{appearance:none;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");background-repeat:no-repeat;background-position:right 12px center;padding-right:40px}
.ds-input:focus,.ds-select:focus,.ds-textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
.ds-input--err{border-color:var(--alert)}
.ds-input--err:focus{box-shadow:0 0 0 3px rgba(229,72,77,.16)}
.ds-error{color:var(--alert);font-size:13px;margin-top:6px;font-weight:500}
.ds-check{display:flex;gap:10px;align-items:flex-start;font-size:14px;margin:10px 0;font-weight:400;color:var(--ink-2)}
.ds-check input,input.ds-check{width:20px;height:20px;min-height:0;flex:0 0 auto;margin-top:2px;accent-color:var(--accent);cursor:pointer}

/* EMPTY STATE — teach, don't apologize. */
.ds-empty{text-align:center;color:var(--slate);padding:var(--s6) var(--s3);
  border:1px dashed var(--line);border-radius:var(--r-lg);background:rgba(255,255,255,.5)}
.ds-empty h3{color:var(--ink);margin-bottom:var(--s1)}

/* SKELETON loaders */
.ds-skel{background:linear-gradient(90deg,var(--paper-2) 25%,#F7F9FC 37%,var(--paper-2) 63%);
  background-size:400% 100%;animation:ds-shimmer 1.3s ease-in-out infinite;border-radius:var(--radius)}
.ds-skel--line{height:14px;margin:var(--s2) 0}
.ds-skel--card{height:84px}
@keyframes ds-shimmer{0%{background-position:100% 0}100%{background-position:0 0}}

/* BOTTOM TAB BAR (mobile) — glassy, active accent with a lifted pill. */
.ds-tabbar{position:fixed;bottom:0;left:0;right:0;z-index:30;
  display:flex;height:calc(58px + env(safe-area-inset-bottom,0));padding-bottom:env(safe-area-inset-bottom,0);
  background:rgba(255,255,255,.9);backdrop-filter:saturate(1.6) blur(14px);-webkit-backdrop-filter:saturate(1.6) blur(14px);
  border-top:1px solid var(--line)}
.ds-tabbar a{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:3px;color:var(--slate);font-size:11px;font-weight:600;position:relative;transition:color .15s;
  border-top:2px solid transparent;min-width:0;text-align:center;line-height:1.15;padding:0 2px}
.ds-tabbar a .ds-tabbar__ico{display:flex;align-items:center;justify-content:center;height:26px;transition:transform .18s var(--ease)}
.ds-tabbar a[aria-current="page"]{color:var(--accent);font-weight:700;border-top-color:var(--accent)}
.ds-tabbar a[aria-current="page"] .ds-tabbar__ico{transform:translateY(-1px)}
.ds-tabbar a .ds-tabbar__dot{position:absolute;top:8px;right:calc(50% - 16px);
  width:8px;height:8px;background:var(--alert);border-radius:50%;box-shadow:0 0 0 2px #fff}
.ds-has-tabs{padding-bottom:calc(58px + env(safe-area-inset-bottom,0))}

/* STICKY primary action bar (Sign / Pay) */
/* A back control that only exists below 900px, where the breadcrumb bar goes
   static and scrolls out of reach inside a job section. */
.fs-back{display:none;margin-bottom:var(--s3)}
.ds-sticky-action{position:sticky;bottom:0;background:rgba(255,255,255,.92);backdrop-filter:blur(10px);
  border-top:1px solid var(--line);padding:var(--s3);box-shadow:0 -6px 20px -8px rgba(16,24,40,.15)}

/* ACTIVATION BAR (pending, unpaid contractor) */
.ds-activate-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  flex-wrap:wrap;background:var(--accent-tint);border-bottom:1px solid #CFE0FB;
  color:var(--accent-ink);padding:10px var(--s3);font-size:14px;font-weight:500}
.ds-activate-bar strong{font-weight:700}
.ds-lock-hint{font-size:12px;color:var(--slate)}

/* TOPBAR — sticky glass, brand mark with gradient. */
.ds-topbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);padding:10px var(--s4);min-height:58px;
  background:rgba(255,255,255,.82);backdrop-filter:saturate(1.6) blur(14px);-webkit-backdrop-filter:saturate(1.6) blur(14px);
  border-bottom:1px solid var(--line)}
.ds-topbar__brand{display:flex;align-items:center;gap:10px;min-width:0}
.ds-topbar__brand img{height:30px;width:auto;max-width:150px;object-fit:contain;border-radius:6px}
.ds-topbar__mark{width:32px;height:32px;border-radius:9px;background:var(--grad-accent);color:var(--on-accent);
  display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-weight:800;font-size:15px;
  flex:0 0 auto;box-shadow:var(--shadow-accent)}
.ds-topbar__name{font-family:var(--font-display);font-weight:700;font-size:1.02rem;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* PROGRESS STEPS (client status strip) */
.ds-progress{display:flex;gap:6px;margin:var(--s3) 0 var(--s1)}
.ds-progress__step{flex:1;height:8px;border-radius:var(--r-pill);background:var(--paper-2);transition:background .3s var(--ease)}
.ds-progress__step.is-on{background:var(--grad-accent)}
.ds-progress__label{font-weight:700;font-size:14px;color:var(--ink);letter-spacing:-.01em}

/* PHOTO STRIP */
.ds-photostrip{display:flex;gap:var(--s2);overflow-x:auto;padding-bottom:var(--s1);-webkit-overflow-scrolling:touch;scroll-snap-type:x proximity}
.ds-photostrip figure{flex:0 0 auto;width:160px;margin:0;scroll-snap-align:start}
.ds-photostrip img{width:160px;height:118px;object-fit:cover;border-radius:var(--radius);background:var(--paper-2);border:1px solid var(--line);box-shadow:var(--shadow-xs)}
.ds-photostrip figcaption{font-size:12px;color:var(--slate);margin-top:6px;line-height:1.3}

/* MESSAGE BUBBLE */
.ds-msg{border:1px solid var(--line);border-radius:var(--radius);padding:var(--s3);margin-bottom:var(--s2);background:#fff;box-shadow:var(--shadow-xs)}
.ds-msg--mine{background:var(--accent-tint);border-color:#CFE0FB}
.ds-msg__meta{font-size:12px;color:var(--slate);margin-bottom:4px;font-weight:500}

/* LIST ROW */
.ds-listrow{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:var(--s3) 0;border-bottom:1px solid var(--line-2)}
.ds-listrow:last-child{border-bottom:none}

/* SNAPSHOT / STAT CARD GRID — real dashboard numbers. */
.ds-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s3)}
.ds-cards .ds-card{margin:0;text-align:left;padding:var(--s3) var(--s4);position:relative;overflow:hidden}
.ds-cards .ds-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--grad-accent);opacity:.9}
.ds-cards .ds-card b{display:block;font-family:var(--font-display);font-size:1.9rem;font-weight:800;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.1;color:var(--ink)}
.ds-cards .ds-card span{font-size:12px;color:var(--slate);font-weight:600;text-transform:uppercase;letter-spacing:.04em}

/* MODAL / BOTTOM SHEET — blurred backdrop, big radius, motion. */
.ds-modal-bg{position:fixed;inset:0;z-index:50;background:rgba(16,24,40,.42);backdrop-filter:blur(4px);
  display:flex;justify-content:center;overflow:auto;padding:var(--s3);animation:ds-fade .18s var(--ease)}
.ds-modal-bg--sheet{align-items:flex-end;padding:0}
.ds-modal-bg--center{align-items:center}
.ds-modal{background:#fff;border-radius:var(--r-xl);width:100%;max-width:540px;padding:var(--s5);box-shadow:var(--shadow-lg);animation:ds-pop .22s var(--ease)}
.ds-modal-bg--sheet .ds-modal{border-radius:var(--r-xl) var(--r-xl) 0 0;max-height:92vh;overflow:auto;padding:var(--s4) var(--s4) calc(var(--s4) + env(safe-area-inset-bottom,0));animation:ds-slideup .26s var(--ease)}
@keyframes ds-fade{from{opacity:0}to{opacity:1}}
@keyframes ds-pop{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}
@keyframes ds-slideup{from{transform:translateY(100%)}to{transform:none}}

/* SEGMENTED sub-tabs — pill group. */
.ds-seg{display:flex;flex-wrap:wrap;gap:6px;margin:var(--s3) 0;padding:5px;background:var(--paper-2);border-radius:var(--radius);width:fit-content;max-width:100%}
.ds-seg button{min-height:36px;padding:0 var(--s3);font-size:13.5px;font-weight:600;color:var(--slate);
  background:transparent;border:none;border-radius:var(--r-sm);cursor:pointer;transition:all .15s var(--ease)}
.ds-seg button:hover{color:var(--ink)}
.ds-seg button[aria-current="true"]{color:var(--accent);background:#fff;box-shadow:var(--shadow-xs)}

/* inline success note */
.ds-note-ok{padding:var(--s3);border-radius:var(--radius);color:var(--ok-ink);background:var(--ok-tint);font-size:14px;font-weight:500}

/* ASSIST watermark bar — api.js prepends this before .ds-topbar in the DOM.
   It used to be position:sticky;top:0 like the topbar below it. Two siblings
   both pinned to the viewport's top:0 do not stack, they overlap: once the
   page scrolled far enough for both to engage, this bar (z-index:60) painted
   over the topbar's brand mark and covered the top of the Help/Log out
   buttons with un-clickable banner. It only has to be seen once per page
   load, not re-pinned on every scroll, so letting it scroll away with the
   page removes the collision entirely and .ds-topbar remains the one sticky
   bar. */
.ds-assist-bar{position:static;display:flex;align-items:center;justify-content:space-between;
  gap:var(--s2);padding:9px var(--s3);background:var(--warn);color:#fff;font-size:13px;font-weight:700;
  letter-spacing:.04em;text-transform:uppercase}
.ds-assist-bar a{color:#fff;text-decoration:underline;text-transform:none;font-weight:600}

/* COMMAND CENTER dense chrome */
.ds-dense h1{font-size:1.28rem}
.ds-dense h2{font-size:1.05rem}
.ds-dense .ds-card{padding:var(--s3)}
/* The table used to carry its own border-radius + overflow:hidden so its corners
   stayed clean, but overflow:hidden on the table also makes the table itself the
   nearest scrolling ancestor for the sticky th below, and since the table never
   scrolls independently (the page scrolls, the table doesn't), the header's
   position:sticky had no scroll context to stick against and just sat there like
   an ordinary row. The rounding and the clip move to .ds-table-wrap instead, so
   the table stops being that ancestor and the header can actually pin as a long
   list scrolls. */
.ds-table{width:100%;border-collapse:separate;border-spacing:0;font-size:13px;background:var(--card)}
.ds-table th{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--slate);font-weight:700;
  text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);background:var(--paper);position:sticky;top:0}
.ds-table td{padding:11px 12px;border-bottom:1px solid var(--line-2);vertical-align:middle}
.ds-table tr:last-child td{border-bottom:none}
.ds-table tbody tr{transition:background .12s}
.ds-table tr.tap{cursor:pointer}
.ds-table tbody tr:hover{background:var(--paper)}
/* overflow-x:auto also promotes overflow-y to auto, which makes this wrapper the
   scrollport the sticky th above pins against. With no height limit the wrapper is
   exactly as tall as the table, so the header has nowhere to travel and still rides
   off the top with the page. A max-height gives a long table its own scroll region,
   which is the context position:sticky needs; short tables never reach it. */
.ds-table-wrap{overflow-x:auto;max-height:70vh;border-radius:var(--radius);border:1px solid var(--line);box-shadow:var(--shadow-xs)}
/* Not inside a modal. The backdrop is already the scroller there (.ds-modal-bg is
   overflow:auto and the centered .ds-modal sets no height of its own), and the one
   table that renders in a modal is the lead detail list, which is built as a th
   label plus a td value PER ROW. Give that wrapper a scroll region and every one
   of those th cells matches the sticky rule above, so the labels pile up in a band
   at the top edge sitting over values they do not belong to. Uncapped, the modal
   scrolls as one block, which is what it did before. */
.ds-modal .ds-table-wrap{max-height:none}
.ds-kanban{display:flex;gap:var(--s3);overflow-x:auto;align-items:flex-start;padding-bottom:var(--s2)}
.ds-kanban__col{flex:0 0 250px;background:var(--paper-2);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s2);transition:background .15s,box-shadow .15s}
.ds-kanban__col.is-dragover{background:var(--accent-tint);box-shadow:inset 0 0 0 2px var(--accent)}
.ds-kanban__col h4{margin:0 0 var(--s2);padding:6px 8px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--slate);font-weight:700}
.ds-kanban__card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:10px var(--s3);margin-bottom:var(--s2);cursor:grab;font-size:13px;box-shadow:var(--shadow-xs);transition:transform .12s,box-shadow .15s}
.ds-kanban__card:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.ds-kanban__card:active{cursor:grabbing}

/* demo bar — app.html inserts this with .ds-topbar.after(bar), so it sits
   right below the topbar in the DOM. Same top:0 sticky collision as the
   assist bar above: the topbar sticks first, then this bar's own top edge
   reaches y=0 and sticks on top of it (z-index:25 over the topbar's 20),
   burying the company name under 'Demo, this is the console you get' and
   killing clicks on the top of the topbar's buttons. Scrolling away with the
   page is fine, the message only needs to be read once, so this is static
   now and .ds-topbar is the only bar that stays pinned. */
.ds-demo-bar{position:static;display:flex;align-items:center;justify-content:space-between;
  gap:var(--s2);padding:9px var(--s3);background:var(--ink);color:var(--paper);font-size:13px;font-weight:500}
.ds-demo-bar a{color:#fff;text-decoration:underline;font-weight:600;white-space:nowrap}

/* install prompt bar */
.ds-install{position:fixed;left:50%;bottom:calc(80px + env(safe-area-inset-bottom,0));transform:translateX(-50%);z-index:99;
  display:flex;gap:var(--s2);align-items:center;background:#fff;border:1px solid var(--line);
  border-radius:var(--r-pill);box-shadow:var(--shadow-lg);padding:8px 8px 8px var(--s3);font-size:14px;max-width:92%}

/* landscape hint (signature) */
.ds-hint{font-size:13px;color:var(--warn-ink);background:var(--warn-tint);padding:10px var(--s3);border-radius:var(--radius);margin:var(--s2) 0}

/* signature pad */
.sigpad,.svc-sig__canvas{width:100%;height:190px;border:2px dashed var(--line);border-radius:var(--radius);
  background:linear-gradient(#fff,#fff) padding-box,repeating-linear-gradient(-45deg,#fff,#fff 10px,#FAFBFD 10px,#FAFBFD 20px);
  touch-action:none;display:block}

/* toast — slide-in with motion */
.ds-toast{position:fixed;left:50%;bottom:calc(96px + env(safe-area-inset-bottom,0));pointer-events:none;transform:translateX(-50%);z-index:99;
  max-width:90%;padding:11px var(--s3);border-radius:var(--r-pill);
  box-shadow:var(--shadow-lg);font-size:14px;font-weight:500;background:var(--ink);color:#fff;
  animation:ds-toast-in .28s var(--ease)}
.ds-toast--ok{background:var(--ok)}
.ds-toast--err{background:var(--alert)}
@keyframes ds-toast-in{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}

/* ================================================================
   MARKETING SITE (.mk-*) — conversion-first, one accent.
   ================================================================ */
/* NAV — sticky glass, full-bleed, with a real mobile menu. */
.mk-nav{position:sticky;top:0;z-index:40;background:rgba(255,255,255,.82);
  backdrop-filter:saturate(1.6) blur(14px);-webkit-backdrop-filter:saturate(1.6) blur(14px);
  border-bottom:1px solid var(--line);transition:background .25s var(--ease),border-color .25s var(--ease)}
.mk-nav__in{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  max-width:1120px;margin:0 auto;padding:11px var(--s4)}
.mk-nav__brand{display:inline-flex;align-items:center;gap:9px;font-family:var(--font-display);
  font-weight:800;font-size:1.24rem;letter-spacing:-.02em;color:var(--ink)}
.mk-nav__brand:hover{color:var(--ink)}
.mk-nav__mark{width:26px;height:26px;border-radius:7px;background:var(--grad-accent);flex:0 0 auto;
  box-shadow:var(--shadow-accent);display:inline-flex;align-items:center;justify-content:center;color:#fff;font-size:14px;font-weight:800}
.mk-nav__links{display:flex;gap:4px;align-items:center}
.mk-nav__links a:not(.ds-btn){color:var(--slate);font-weight:600;font-size:14.5px;padding:8px 12px;border-radius:var(--r-sm)}
.mk-nav__links a:not(.ds-btn):hover{color:var(--ink);background:var(--paper)}
.mk-nav__cta{display:flex;gap:8px;align-items:center;margin-left:var(--s2)}
.mk-nav__toggle{display:none;width:42px;height:42px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:#fff;cursor:pointer;align-items:center;justify-content:center;box-shadow:var(--shadow-xs)}
.mk-nav__toggle svg{width:22px;height:22px;stroke:var(--ink)}
.mk-nav__panel{display:none}
@media(max-width:820px){
  .mk-nav__links{display:none}
  .mk-nav__toggle{display:inline-flex}
  .mk-nav.is-open .mk-nav__panel{display:block;position:absolute;left:0;right:0;top:100%;
    background:#fff;border-bottom:1px solid var(--line);box-shadow:var(--shadow-lg);padding:var(--s3) var(--s4) var(--s4)}
  .mk-nav.is-open .mk-nav__panel a:not(.ds-btn){display:block;padding:13px 6px;font-size:16px;font-weight:600;color:var(--ink);border-bottom:1px solid var(--line-2)}
  .mk-nav.is-open .mk-nav__panel .ds-btn{margin-top:12px;width:100%}
}

.mk-wrap{max-width:1120px;margin:0 auto;padding-left:var(--s4);padding-right:var(--s4)}
.mk-section{padding-top:clamp(48px,8vw,104px);padding-bottom:clamp(48px,8vw,104px)}
.mk-h1{font-family:var(--font-display);font-weight:800;line-height:1.02;letter-spacing:-.03em;
  font-size:clamp(2.5rem,6vw,4.4rem);color:var(--ink);margin:0 0 var(--s3)}
.mk-h2{font-family:var(--font-display);font-weight:800;letter-spacing:-.025em;font-size:clamp(1.7rem,3.5vw,2.6rem);color:var(--ink);margin:0 0 var(--s3)}
.mk-lede{font-size:clamp(1.08rem,2vw,1.32rem);color:var(--slate);max-width:36ch;margin:0 0 var(--s4);line-height:1.5}
.mk-eyebrow{font-family:var(--font-display);font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  font-size:12.5px;color:var(--accent);margin:0 0 var(--s2)}

.mk-hero{display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(24px,5vw,72px);align-items:center;position:relative}
@media(max-width:820px){ .mk-hero{grid-template-columns:1fr} .mk-hero__art{order:-1} }
.mk-cta-row{display:flex;gap:var(--s2);flex-wrap:wrap}
.mk-cta-row .ds-btn{width:auto}

/* phone frame */
.mk-phone{width:280px;max-width:78vw;margin:0 auto;background:#0B1220;border-radius:40px;
  padding:12px;box-shadow:0 40px 80px -24px rgba(16,24,40,.5),0 0 0 1px rgba(16,24,40,.06)}
.mk-phone__screen{background:var(--paper);border-radius:28px;overflow:hidden;aspect-ratio:9/19;display:flex;flex-direction:column}
.mk-phone__bar{background:#fff;border-bottom:1px solid var(--line);padding:12px 16px;font-size:12px;font-weight:700;color:var(--ink);display:flex;justify-content:space-between;align-items:center}
.mk-phone__body{padding:16px;flex:1;display:flex;flex-direction:column;gap:12px}
.mk-mini-card{background:#fff;border:1px solid var(--line);border-radius:14px;padding:14px;font-size:12px;box-shadow:var(--shadow-xs)}
.mk-mini-btn{background:var(--grad-accent);color:#fff;text-align:center;border-radius:14px;padding:14px;font-weight:700;font-size:14px;box-shadow:var(--shadow-accent)}
.mk-mini-amt{font-size:24px;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.02em}

.mk-pain{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4)}
@media(max-width:720px){ .mk-pain{grid-template-columns:1fr;gap:var(--s3)} }
.mk-pain p{font-size:1.18rem;color:var(--ink);font-weight:600;line-height:1.35;margin:0;
  padding-left:var(--s3);border-left:3px solid var(--accent)}

.mk-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4)}
@media(max-width:720px){ .mk-steps{grid-template-columns:1fr} }
.mk-step__cap{font-family:var(--font-display);font-weight:700;font-size:1.15rem;margin-top:var(--s2);color:var(--ink)}
.mk-step__n{font-family:var(--font-display);color:var(--accent);font-weight:800}

/* dark paper-trail section */
.mk-dark{background:radial-gradient(1200px 500px at 80% -10%,rgba(46,107,240,.25),transparent 60%),var(--ink);color:var(--paper)}
.mk-dark .mk-h2{color:var(--paper)}
.mk-dark .mk-proof{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4);margin-top:var(--s4)}
@media(max-width:720px){ .mk-dark .mk-proof{grid-template-columns:1fr} }
.mk-dark .mk-proof h3{color:var(--paper);font-family:var(--font-display);margin:0 0 6px}
.mk-dark .mk-proof p{color:var(--on-ink);margin:0;font-size:15px}

/* price block */
.mk-price{text-align:center}
.mk-price__num{font-family:var(--font-display);font-weight:800;font-size:clamp(3.5rem,10vw,6.5rem);letter-spacing:-.04em;
  background:var(--grad-accent);-webkit-background-clip:text;background-clip:text;color:transparent;line-height:1}
.mk-price__num span{font-size:.28em;color:var(--slate);font-weight:700;-webkit-text-fill-color:var(--slate)}

/* services strip */
.mk-svc-strip{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s3)}
@media(max-width:720px){ .mk-svc-strip{grid-template-columns:1fr} }
.mk-svc-card{display:block;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s4);color:var(--ink);box-shadow:var(--shadow-xs);transition:transform .15s var(--ease),box-shadow .18s}
.mk-svc-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:#DBE1EA}
.mk-svc-card h3{font-family:var(--font-display);margin:0 0 6px}
.mk-svc-card p{color:var(--slate);margin:0;font-size:15px}

/* testimonial slots */
.mk-quotes{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s3)}
@media(max-width:720px){ .mk-quotes{grid-template-columns:1fr} }
.mk-quote{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s4);box-shadow:var(--shadow-xs)}
.mk-quote blockquote{margin:0 0 var(--s2);font-size:1.05rem;color:var(--ink);line-height:1.5}
.mk-quote cite{color:var(--slate);font-style:normal;font-size:14px;font-weight:600}
.mk-todo{opacity:.55}

/* footer */
.mk-footer{border-top:1px solid var(--line);background:#fff}
.mk-footer__in{max-width:1120px;margin:0 auto;padding:var(--s6) var(--s4);display:flex;flex-wrap:wrap;gap:var(--s4);justify-content:space-between}
.mk-footer a{color:var(--slate);font-size:14px;display:block;padding:4px 0}
.mk-footer a:hover{color:var(--ink)}
.mk-footer h4{font-family:var(--font-display);font-size:12.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink);margin:0 0 var(--s2)}

/* service landing + intake */
.mk-svc-hero{max-width:720px}
.mk-svc-list{list-style:none;padding:0;margin:var(--s3) 0}
.mk-svc-list li{padding:9px 0 9px 30px;position:relative;color:var(--ink)}
.mk-svc-list li::before{content:'✓';position:absolute;left:0;top:8px;color:#fff;background:var(--ok);font-weight:700;
  width:20px;height:20px;border-radius:50%;font-size:12px;display:flex;align-items:center;justify-content:center}
.mk-disclosure{background:var(--warn-tint);border:1px solid #EBD3A0;border-radius:var(--radius);padding:var(--s3) var(--s4);color:#7A5A12;font-size:15px;margin:var(--s3) 0}
.mk-floor{font-weight:600;color:var(--slate)}
.mk-disclosure--ok{background:var(--ok-tint);border-color:#A9D6B8;color:#0E5A2E}

.mk-intake{max-width:560px;background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s5);box-shadow:var(--shadow-sm)}
.mk-intake__progress{height:6px;background:var(--paper-2);border-radius:var(--r-pill);overflow:hidden;margin-bottom:var(--s4)}
.mk-intake__bar{height:100%;background:var(--grad-accent);width:0;transition:width .3s var(--ease)}
.mk-step[hidden]{display:none}
.mk-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.mk-intake__nav{display:flex;gap:var(--s2);margin-top:var(--s4)}
.mk-bypass{margin-top:var(--s3);font-size:14px}

/* ================================================================
   INTERACTIVE COMPONENTS (.svc-*) — the logic-heavy widgets mounted into
   the console/portals (calendar, selector, uploader, wizard, negotiation,
   demo). Now fully styled to match the system.
   ================================================================ */

/* --- Field Ops calendar --- */
.svc-cal__toolbar{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s3)}
.svc-cal__title{font-family:var(--font-display);font-weight:800;font-size:1.15rem;letter-spacing:-.02em;margin-right:auto}
.svc-cal__btn{min-width:38px;height:38px;padding:0 var(--s3);border:1px solid var(--line);background:#fff;
  border-radius:var(--r-sm);font-weight:600;color:var(--ink);cursor:pointer;box-shadow:var(--shadow-xs);transition:all .12s}
.svc-cal__btn:hover{border-color:var(--slate-2);box-shadow:var(--shadow-sm)}
.svc-cal__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.svc-cal__dow{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--slate-3);text-align:center;padding:4px 0}
.svc-cal__day{min-height:96px;background:#fff;border:1px solid var(--line);border-radius:var(--r-sm);padding:6px;
  display:flex;flex-direction:column;gap:3px;cursor:pointer;transition:border-color .12s,background .12s}
.svc-cal__day:hover{border-color:var(--slate-2)}
.svc-cal__day.is-other-month{background:var(--paper);opacity:.5}
.svc-cal__day.is-today{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.svc-cal__day.is-dragover{background:var(--accent-tint);border-color:var(--accent)}
.svc-cal__daynum{font-size:12px;font-weight:700;color:var(--slate);align-self:flex-end}
.svc-cal__day.is-today .svc-cal__daynum{color:var(--accent)}
.svc-cal__job{background:var(--accent-tint);color:var(--accent-ink);border-radius:6px;padding:3px 6px;font-size:11px;font-weight:600;
  cursor:grab;display:flex;flex-direction:column;line-height:1.2;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.svc-cal__job:active{cursor:grabbing}
.svc-cal__job.is-blocked{background:var(--alert-tint);color:var(--alert-ink)}
.svc-cal__job.is-done{background:var(--ok-tint);color:var(--ok-ink)}
.svc-cal__job.is-inprogress{background:var(--warn-tint);color:var(--warn-ink)}
.svc-cal__job-crew{font-weight:500;opacity:.8;font-size:10px}
.svc-cal__more{font-size:11px;font-weight:600;color:var(--accent);cursor:pointer;
  display:block;width:100%;padding:8px 4px;min-height:var(--tap);text-align:left}
@media(max-width:640px){
  /* Seven equal-fraction columns on a 375px screen leave ~20px per job chip —
     room for two characters and an ellipsis, so a job can't be told apart from
     any other without tapping it. A minimum column width plus horizontal
     scroll keeps every chip wide enough to show a real title. */
  .svc-cal__grid{grid-template-columns:repeat(7,minmax(88px,1fr));overflow-x:auto}
  .svc-cal__day{min-height:64px}
  .svc-cal__job-crew{display:none}
}

/* --- service selector (typeahead multi-select) --- */
.svc-sel{position:relative}
.svc-sel__chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.svc-sel__chip{display:inline-flex;align-items:center;gap:6px;background:var(--accent-tint);color:var(--accent-ink);
  border-radius:var(--r-pill);padding:5px 6px 5px 12px;font-size:13px;font-weight:600}
.svc-sel__chip-x{position:relative;border:none;background:rgba(29,78,216,.15);color:var(--accent-ink);width:18px;height:18px;border-radius:50%;
  cursor:pointer;font-size:13px;line-height:1;display:flex;align-items:center;justify-content:center}
.svc-sel__chip-x:hover{background:var(--accent);color:#fff}
.svc-sel__input{width:100%;min-height:var(--tap);padding:0 var(--s3);font-size:15px;color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:var(--radius);transition:border-color .15s,box-shadow .15s}
.svc-sel__input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
.svc-sel__menu{position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:40;max-height:280px;overflow:auto;
  background:#fff;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-lg);padding:6px}
.svc-sel__menu:not(.is-open){display:none}
.svc-sel__group{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--slate-3);padding:8px 10px 4px}
.svc-sel__opt{padding:9px 10px;border-radius:var(--r-sm);cursor:pointer;font-size:14px;font-weight:500}
.svc-sel__opt:hover,.svc-sel__opt.is-active{background:var(--accent-tint);color:var(--accent-ink)}
.svc-sel__other{color:var(--accent);font-weight:600}

/* --- uploader --- */
.svc-up__zone{border:2px dashed var(--line);border-radius:var(--r-lg);padding:var(--s5) var(--s3);text-align:center;
  color:var(--slate);font-weight:500;cursor:pointer;background:var(--paper);transition:all .15s}
.svc-up__zone:hover,.svc-up__zone.is-dragover{border-color:var(--accent);background:var(--accent-tint);color:var(--accent-ink)}
.svc-up__list{margin-top:var(--s3);display:flex;flex-direction:column;gap:var(--s2)}
.svc-up__item{display:flex;gap:var(--s3);align-items:center;background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:10px}
.svc-up__item.is-done{border-color:#B7E4C6}.svc-up__item.is-error{border-color:#F3B9BB}
.svc-up__thumb{width:44px;height:44px;border-radius:var(--r-sm);background:var(--paper-2);flex:0 0 auto;overflow:hidden;
  display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;color:var(--slate)}
.svc-up__thumb img{width:100%;height:100%;object-fit:cover}
.svc-up__name{flex:1;font-size:14px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.svc-up__bar{flex:0 0 90px;height:6px;background:var(--paper-2);border-radius:var(--r-pill);overflow:hidden}
.svc-up__bar-fill{height:100%;background:var(--grad-accent);width:0;transition:width .2s var(--ease)}
.svc-up__item.is-done .svc-up__bar-fill{background:var(--ok)}

/* --- wizard --- */
.svc-wiz__progress{display:flex;gap:6px;margin-bottom:var(--s4)}
.svc-wiz__step{flex:1;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--slate-3);
  padding-top:12px;border-top:3px solid var(--paper-2);transition:all .2s}
.svc-wiz__step.is-current{color:var(--accent);border-top-color:var(--accent)}
.svc-wiz__step.is-done{color:var(--ok);border-top-color:var(--ok)}
.svc-wiz__hint{color:var(--slate);font-size:14px;margin-bottom:var(--s3)}
.svc-wiz__summary{font-size:1.1rem;font-weight:600}
.svc-wiz__goals{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
@media(max-width:520px){ .svc-wiz__goals{grid-template-columns:1fr} }
.svc-wiz__goal{padding:var(--s3);border:1px solid var(--line);border-radius:var(--radius);background:#fff;cursor:pointer;
  font-weight:600;font-size:14px;text-align:left;transition:all .12s}
.svc-wiz__goal:hover{border-color:var(--slate-2)}
.svc-wiz__goal[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-tint);color:var(--accent-ink);box-shadow:inset 0 0 0 1px var(--accent)}
.svc-wiz__nav{display:flex;gap:var(--s2);margin-top:var(--s4)}
.svc-wiz__btn{flex:1;min-height:var(--tap);border-radius:var(--radius);font-weight:600;font-size:15px;cursor:pointer;border:1px solid transparent}
.svc-wiz__btn[data-nav="next"]{background:var(--grad-accent);color:#fff;box-shadow:var(--shadow-accent)}
.svc-wiz__btn[data-nav="back"]{background:#fff;color:var(--ink);border-color:var(--line);flex:0 0 auto;padding:0 var(--s4)}
.svc-wiz__skip{display:block;margin:var(--s3) auto 0;background:none;border:none;color:var(--slate);font-size:14px;cursor:pointer;text-decoration:underline}

/* --- change-order negotiation --- */
.svc-nego{border:1px solid var(--line);border-radius:var(--radius);padding:var(--s3);background:#fff}
.svc-nego__price{display:flex;align-items:center;gap:var(--s2);font-weight:700;font-size:1.05rem}
.svc-nego__status{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--slate);background:var(--paper-2);padding:3px 8px;border-radius:var(--r-pill)}
.svc-nego__history{margin:var(--s3) 0;border-top:1px solid var(--line-2);padding-top:var(--s2)}
.svc-nego__offer{display:flex;gap:var(--s2);align-items:center;font-size:13px;padding:5px 0}
.svc-nego__offer-who{font-weight:600;min-width:74px}
.svc-nego__offer-price{font-variant-numeric:tabular-nums;font-weight:700}
.svc-nego__offer-outcome{font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--slate-3)}
.svc-nego__offer.is-accepted{color:var(--ok)}.svc-nego__offer.is-declined{color:var(--alert)}
.svc-nego__actions{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s3)}
.svc-nego__btn{min-height:44px;border-radius:var(--radius);font-weight:600;cursor:pointer;border:1px solid var(--line);background:#fff}
.svc-nego__btn[data-act="accept"]{background:var(--ok);color:#fff;border-color:transparent}
.svc-nego__btn[data-act="counter"],.svc-nego__btn[data-act="recounter"]{background:var(--grad-accent);color:#fff;border-color:transparent}
.svc-nego__input{width:100%;min-height:44px;padding:0 var(--s3);border:1px solid var(--line);border-radius:var(--radius);font-size:15px}
.svc-nego__hint{font-size:13px;color:var(--slate)}

/* --- data grid (table + kanban) reuse the dense chrome --- */
.svc-grid__filter{width:100%;max-width:280px;min-height:40px;padding:0 var(--s3);border:1px solid var(--line);border-radius:var(--radius);margin-bottom:var(--s3);font-size:14px}
.svc-grid__table{width:100%;border-collapse:separate;border-spacing:0;font-size:13.5px;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-xs)}
.svc-grid__table th{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--slate);font-weight:700;text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);background:var(--paper)}
.svc-grid__table th.is-sorted-asc::after{content:' ↑';color:var(--accent)}
.svc-grid__table th.is-sorted-desc::after{content:' ↓';color:var(--accent)}
.svc-grid__table td{padding:11px 12px;border-bottom:1px solid var(--line-2)}
.svc-grid__row{cursor:pointer;transition:background .12s}
.svc-grid__row:hover{background:var(--paper)}
.svc-kb{display:flex;gap:var(--s3);overflow-x:auto;align-items:flex-start;padding-bottom:var(--s2)}
.svc-kb__col{flex:0 0 250px;background:var(--paper-2);border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s2);transition:background .15s,box-shadow .15s}
.svc-kb__col.is-dragover{background:var(--accent-tint);box-shadow:inset 0 0 0 2px var(--accent)}
.svc-kb__col-head{padding:6px 8px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--slate);font-weight:700}
.svc-kb__card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:10px var(--s3);margin-bottom:var(--s2);cursor:grab;font-size:13px;box-shadow:var(--shadow-xs)}
.svc-kb__card:hover{box-shadow:var(--shadow-sm)}

/* --- demo widget --- */
.svc-demo{border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;background:#fff;box-shadow:var(--shadow-md)}
.svc-demo__toggle{display:flex;background:var(--paper-2);padding:5px;gap:5px;margin:var(--s3);border-radius:var(--radius)}
.svc-demo__toggle-btn{flex:1;min-height:38px;border:none;background:transparent;border-radius:var(--r-sm);font-weight:600;font-size:13px;color:var(--slate);cursor:pointer}
.svc-demo__toggle-btn.is-active{background:#fff;color:var(--accent);box-shadow:var(--shadow-xs)}
.svc-demo__view{padding:0 var(--s3) var(--s3)}
.svc-demo__head{display:flex;justify-content:space-between;font-weight:700;padding:var(--s2) 0;border-bottom:1px solid var(--line-2);margin-bottom:var(--s2)}
.svc-demo__photos{display:flex;gap:8px;overflow-x:auto;margin-bottom:var(--s2)}
.svc-demo__photo img{width:120px;height:88px;object-fit:cover;border-radius:var(--r-sm)}
.svc-demo__row{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid var(--line-2);font-size:14px}
.svc-demo__chip{font-size:11px;font-weight:700;padding:4px 10px;border-radius:var(--r-pill)}
.svc-demo__chip.is-paid,.svc-demo__chip.is-signed{background:var(--ok-tint);color:var(--ok-ink)}
.svc-demo__chip.is-due,.svc-demo__chip.is-needs{background:var(--alert-tint);color:var(--alert-ink)}
.svc-demo__cta{display:block;margin:var(--s3);text-align:center;background:var(--grad-accent);color:#fff;padding:13px;border-radius:var(--radius);font-weight:700;box-shadow:var(--shadow-accent)}
.svc-demo__empty{padding:var(--s6);text-align:center;color:var(--slate)}

/* --- booking embed --- */
.svc-book__frame{width:100%;height:640px;border:1px solid var(--line);border-radius:var(--r-lg);background:#fff}
.svc-book__fallback{display:none;margin-top:var(--s2)}.svc-book__fallback.is-visible{display:block}

/* ================================================================
   RESPONSIVE + MOTION
   ================================================================ */
@media(min-width:820px){
  h1{font-size:1.7rem}
  .ds-wrap{padding:var(--s5) var(--s4)}
}
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
  .ds-btn:hover,.ds-card--tap:hover,.mk-svc-card:hover{transform:none}
}

/* ================================================================
   MARKETING KIT v2 — sections that carry the sales narrative.
   (trust strip · two-sided product peek · bands · feature grid ·
    pricing plans · add-ons · FAQ) All token-driven, no image assets.
   ================================================================ */

/* centered section header */
.mk-head{text-align:center;max-width:660px;margin:0 auto var(--s5)}
.mk-head .mk-lede{margin:0 auto;max-width:54ch}
.mk-cta-row--center{justify-content:center}

/* trust strip under the hero */
.mk-trust{display:flex;flex-wrap:wrap;gap:9px 22px;align-items:center}
.mk-trust__item{font-size:13px;font-weight:600;color:var(--slate-3);letter-spacing:.01em;display:inline-flex;align-items:center;gap:7px}
.mk-trust__item::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--ok);flex:0 0 auto}

/* tinted / dark full-bleed bands for rhythm */
.mk-band{background:var(--paper-2);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}

/* desktop "window" frame — the console peek */
.mk-window{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-lg)}
.mk-window__bar{display:flex;align-items:center;gap:7px;padding:11px 14px;background:var(--paper);border-bottom:1px solid var(--line)}
.mk-window__dot{width:11px;height:11px;border-radius:50%;background:#D6DBE3;flex:0 0 auto}
.mk-window__title{margin-left:8px;font-size:12px;font-weight:700;color:var(--slate)}
.mk-window__body{padding:var(--s4)}

/* two-sided product peek (console + client portal) */
.mk-peek{display:grid;grid-template-columns:1.1fr .9fr;gap:clamp(24px,5vw,56px);align-items:center}
@media(max-width:860px){ .mk-peek{grid-template-columns:1fr;gap:var(--s5)} .mk-peek__art{order:-1} }

/* mini folder grid shown inside the console peek — a real taste of the app */
.mk-folders{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
@media(max-width:520px){ .mk-folders{grid-template-columns:repeat(2,1fr)} }
.mk-folder{border:1px solid var(--line);border-radius:var(--radius);padding:12px;background:var(--card);box-shadow:var(--shadow-xs)}
.mk-folder__ico{color:var(--accent);display:block;margin-bottom:7px}
.mk-folder__name{font-size:12.5px;font-weight:700;color:var(--ink);line-height:1.2}
.mk-folder__sub{font-size:11px;color:var(--slate);margin-top:1px}
.mk-folder__badge{display:inline-block;margin-top:7px;font-size:10px;font-weight:800;padding:2px 8px;border-radius:var(--r-pill);background:var(--alert-tint);color:var(--alert-ink);letter-spacing:.02em}
.mk-folder__badge.is-ok{background:var(--ok-tint);color:var(--ok-ink)}
.mk-folder__badge.is-warn{background:var(--warn-tint);color:var(--warn-ink)}

/* feature grid (icon + title + line) */
.mk-features{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s5) var(--s4)}
@media(max-width:820px){ .mk-features{grid-template-columns:1fr;gap:var(--s4)} }
.mk-feature__ico{width:42px;height:42px;border-radius:12px;background:var(--accent-tint);color:var(--accent);display:flex;align-items:center;justify-content:center;margin-bottom:13px}
.mk-feature h3{margin:0 0 5px}
.mk-feature p{color:var(--slate);margin:0;font-size:15px;line-height:1.5}

/* pricing plans */
.mk-plans{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4);max-width:840px;margin:0 auto;align-items:stretch}
@media(max-width:760px){ .mk-plans{grid-template-columns:1fr;gap:var(--s5)} }
.mk-plan{position:relative;background:var(--card);border:1px solid var(--line);border-radius:var(--r-xl);padding:var(--s5);box-shadow:var(--shadow-sm);display:flex;flex-direction:column;text-align:left}
.mk-plan--featured{border-color:var(--accent);box-shadow:var(--shadow-md)}
.mk-plan__tag{position:absolute;top:-13px;left:var(--s5);background:var(--grad-accent);color:#fff;font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:5px 12px;border-radius:var(--r-pill);box-shadow:var(--shadow-accent)}
.mk-plan__name{font-family:var(--font-display);font-weight:800;font-size:1.25rem;margin:0}
.mk-plan__who{color:var(--slate);font-size:14px;margin:3px 0 var(--s3)}
.mk-plan__price{font-family:var(--font-display);font-weight:800;font-size:2.7rem;letter-spacing:-.03em;color:var(--ink);line-height:1;font-variant-numeric:tabular-nums}
.mk-plan__price span{font-size:1rem;font-weight:600;color:var(--slate);letter-spacing:0}
.mk-plan__annual{font-size:13px;color:var(--slate);margin-top:6px}
.mk-plan__feat{list-style:none;padding:0;margin:var(--s4) 0;flex:1}
.mk-plan__feat li{padding:7px 0 7px 28px;position:relative;font-size:14.5px;color:var(--ink);line-height:1.45}
.mk-plan__feat li::before{content:'✓';position:absolute;left:0;top:5px;color:#fff;background:var(--ok);width:19px;height:19px;border-radius:50%;font-size:11px;display:flex;align-items:center;justify-content:center;font-weight:800}
.mk-plan__feat li.is-plus{font-weight:700}
.mk-plan__feat li.is-plus::before{background:var(--accent)}
/* "Everything in Contractor ✓" then a plus emoji on its own centered line,
   directly above the General Contractor features it is adding to. */
.mk-plan__feat li.is-plusmark{padding:2px 0 6px;text-align:center;font-size:20px;line-height:1}
.mk-plan__feat li.is-plusmark::before{content:none;display:none}
.mk-seats{max-width:840px;margin:var(--s4) auto 0;text-align:center;color:var(--slate);font-size:15px}

/* add-ons */
.mk-addons{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3);max-width:940px;margin:var(--s4) auto 0}
.mk-addon{border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s3) var(--s4);background:var(--card);box-shadow:var(--shadow-xs)}
.mk-addon strong{display:block;color:var(--ink);font-size:15px}
.mk-addon span{font-size:13px;color:var(--slate)}
.mk-addon b{font-variant-numeric:tabular-nums;color:var(--accent);font-weight:800}

/* FAQ (native details/summary) */
.mk-faq{max-width:760px;margin:0 auto}
.mk-faq__item{border:1px solid var(--line);border-radius:var(--radius);background:var(--card);margin-bottom:10px;box-shadow:var(--shadow-xs)}
.mk-faq__item summary{list-style:none;cursor:pointer;padding:16px 18px;font-weight:700;color:var(--ink);display:flex;justify-content:space-between;align-items:center;gap:12px}
.mk-faq__item summary::-webkit-details-marker{display:none}
.mk-faq__item summary::after{content:'+';font-size:22px;font-weight:400;color:var(--accent);line-height:1}
.mk-faq__item[open] summary::after{content:'\2212'}
.mk-faq__a{padding:0 18px 16px;color:var(--slate);font-size:15px;line-height:1.6}
.mk-faq__a a{font-weight:600}

/* ================================================================
   FOLDER SYSTEM (.fs-*) — the contractor/GC console as a file explorer.
   Breadcrumb = navigation. Desktop: a sidebar rail + main pane. Mobile:
   the rail collapses; breadcrumb + big tap targets carry navigation.
   ================================================================ */
.fs{display:flex;align-items:stretch;min-height:calc(100vh - var(--topbar-h))}
.fs__side{display:none}
@media(min-width:900px){
  .fs__side{display:flex;flex-direction:column;flex:0 0 250px;width:250px;background:#fff;
    border-right:1px solid var(--line);position:sticky;top:var(--topbar-h);height:calc(100vh - var(--topbar-h));overflow:auto;padding:12px 12px 24px}
}
.fs__main{flex:1;min-width:0;display:flex;flex-direction:column}
.fs__grouplabel{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--slate-3);padding:16px 10px 6px}
.fs__navitem{display:flex;align-items:center;gap:11px;height:40px;padding:0 12px;border-radius:var(--radius);
  color:var(--slate);font-weight:600;font-size:14px;cursor:pointer;transition:background .12s,color .12s;width:100%;border:none;background:none;text-align:left}
.fs__navitem:hover{background:var(--paper);color:var(--ink)}
.fs__navitem[aria-current="page"]{background:var(--accent-tint);color:var(--accent)}
.fs__navitem svg{flex:0 0 auto}
.fs__navitem .fs__count{margin-left:auto;font-size:11px;font-weight:700;color:var(--slate-3)}
.fs__navitem[aria-current="page"] .fs__count{color:var(--accent)}
.fs__navitem .fs__dot{margin-left:auto;width:8px;height:8px;border-radius:50%;background:var(--alert)}

/* breadcrumb bar (the navigation spine) */
.fs-crumbs{display:flex;align-items:center;gap:7px;flex-wrap:wrap;padding:11px var(--s4);
  border-bottom:1px solid var(--line);background:rgba(255,255,255,.75);backdrop-filter:saturate(1.4) blur(8px);
  -webkit-backdrop-filter:saturate(1.4) blur(8px);position:sticky;top:var(--topbar-h);z-index:15}
.fs-crumbs button{font-size:14px;color:var(--slate);font-weight:600;background:none;border:none;cursor:pointer;padding:2px 2px}
.fs-crumbs button:hover{color:var(--accent)}
.fs-crumbs .fs-crumbs__sep{color:var(--slate-2)}
.fs-crumbs .fs-crumbs__cur{font-size:14px;color:var(--ink);font-weight:700}

.fs-body{padding:var(--s4);max-width:1120px;width:100%;margin:0 auto}

/* toolbar (title + actions) */
.fs-toolbar{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s4);flex-wrap:wrap}
.fs-toolbar h1{margin:0;font-size:1.45rem}
.fs-toolbar .fs-toolbar__spacer{margin-left:auto}

/* folder / file grid */
.fs-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(184px,1fr));gap:var(--s3)}
.fs-tile{display:block;text-align:left;background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  padding:16px;cursor:pointer;box-shadow:var(--shadow-xs);position:relative;
  transition:transform .14s var(--ease),box-shadow .16s,border-color .16s;width:100%}
.fs-tile:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:#DBE1EA}
.fs-tile:active{transform:translateY(0)}
.fs-tile__ico{color:var(--accent);margin-bottom:10px;display:block}
.fs-tile__ico.is-file{color:var(--slate)}
.fs-tile__name{font-weight:700;font-size:14.5px;color:var(--ink);line-height:1.25;word-break:break-word}
.fs-tile__sub{font-size:12.5px;color:var(--slate);margin-top:2px}
.fs-tile__badge{position:absolute;top:13px;right:13px}

/* file list rows */
.fs-list{background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-xs)}
.fs-file{display:flex;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid var(--line-2);cursor:pointer;transition:background .12s;width:100%;border:none;background:#fff;text-align:left}
.fs-file:last-child{border-bottom:none}
.fs-file:hover{background:var(--paper)}
.fs-file__ico{color:var(--slate);flex:0 0 auto;display:flex}
.fs-file__main{flex:1;min-width:0}
.fs-file__name{font-weight:600;font-size:14px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fs-file__meta{font-size:12px;color:var(--slate);margin-top:1px}
.fs-file__right{flex:0 0 auto;display:flex;align-items:center;gap:10px}

/* small section label inside a folder view */
.fs-sec{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--slate);margin:var(--s5) 0 var(--s2)}
.fs-sec:first-child{margin-top:0}

/* global search results dropdown */
.fs-search{position:relative;flex:1;max-width:420px}
.fs-search input{width:100%;min-height:40px;padding:0 var(--s3);border:1px solid var(--line);border-radius:var(--r-pill);
  font-size:14px;background:var(--paper)}
.fs-search input:focus{outline:none;border-color:var(--accent);background:#fff;box-shadow:0 0 0 3px var(--accent-glow)}
@media(max-width:640px){ .fs-search{max-width:none} }

/* ================================================================
   MARKETING KIT v3 — the ARGUMENT layer (not the cabinet layer).
   Type does the work. Cards are rationed. Rhythm varies by section.
   Used by the rebuilt homepage: mirror · turn · clock · fork · statement.
   ================================================================ */

/* a huge one-sentence statement — the biggest thing on its screen */
.mk-statement{max-width:18ch;font-family:var(--font-display);font-weight:800;
  font-size:clamp(2.3rem,7vw,4.8rem);line-height:1.02;letter-spacing:-.03em;color:var(--ink);margin:0}
.mk-statement--wide{max-width:24ch}
.mk-statement em{font-style:normal;color:var(--accent)}

/* THE MIRROR — plain lines, lots of air, zero cards */
.mk-mirror p{font-size:clamp(1.2rem,2.6vw,1.7rem);line-height:1.4;color:var(--ink);
  max-width:30ch;margin:0 0 var(--s5);font-weight:500}
.mk-mirror__turn{color:var(--accent)!important;font-weight:700;max-width:34ch}

/* THE TURN — one wide human paragraph */
.mk-turn p{font-size:clamp(1.12rem,2.2vw,1.45rem);line-height:1.5;color:var(--ink);max-width:42ch;margin:0 0 var(--s3)}

/* THE 6-MINUTE CLOCK — the timestamps ARE the argument */
.mk-clock{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,72px);align-items:center}
@media(max-width:860px){.mk-clock{grid-template-columns:1fr} .mk-clock__art{order:-1}}
.mk-clock__step{display:flex;gap:18px;padding:20px 0;border-top:1px solid var(--line)}
.mk-clock__step:first-child{border-top:none;padding-top:0}
.mk-clock__time{font-family:var(--font-display);font-weight:800;font-variant-numeric:tabular-nums;
  color:var(--accent);font-size:1.05rem;flex:0 0 86px;letter-spacing:-.01em}
.mk-clock__what strong{display:block;font-size:1.1rem;color:var(--ink);margin-bottom:2px}
.mk-clock__what span{color:var(--slate);font-size:14.5px}

/* THE FORK — two doors, equal weight, honestly different */
.mk-fork{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4);max-width:900px;margin:0 auto}
@media(max-width:720px){.mk-fork{grid-template-columns:1fr}}
.mk-door{display:block;text-align:left;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-xl);padding:var(--s5);box-shadow:var(--shadow-sm);color:var(--ink);
  transition:transform .16s var(--ease),box-shadow .18s,border-color .18s}
.mk-door:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:var(--accent);color:var(--ink)}
.mk-door__eyebrow{font-size:12.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--slate)}
.mk-door h3{font-family:var(--font-display);font-weight:800;font-size:1.5rem;letter-spacing:-.02em;margin:10px 0 6px;color:var(--ink)}
.mk-door p{color:var(--slate);font-size:15px;margin:0 0 var(--s4);line-height:1.5}
.mk-door__price{font-family:var(--font-display);font-weight:800;font-size:1.5rem;color:var(--ink);font-variant-numeric:tabular-nums}
.mk-door__price span{font-size:.85rem;font-weight:600;color:var(--slate)}
.mk-door__go{display:inline-flex;align-items:center;gap:6px;margin-top:var(--s3);font-weight:700;color:var(--accent)}

/* single line alone in white (the accent aside) */
.mk-aside{font-size:clamp(1.1rem,2.2vw,1.5rem);font-weight:600;color:var(--ink);max-width:36ch;line-height:1.4}
.mk-aside--accent{color:var(--accent)}

/* a quiet under-hero link (demo as text, not a twin button) */
.mk-textlink{display:inline-flex;align-items:center;gap:6px;font-weight:600;color:var(--accent)}
.mk-textlink:hover{color:var(--accent-ink)}

/* ================================================================
   MOTION — the ONLY sanctioned micro-motion (design plan §6.7):
   status chips settle from neutral grey to their color on first view.
   Everything else stays still. Honored-off under reduced-motion by the
   global block above.
   ================================================================ */
@keyframes ds-chip-settle{ from{ background:var(--neutral-tint); color:var(--slate); } }
.ds-chip--ok,.ds-chip--alert,.ds-chip--warn{ animation:ds-chip-settle .5s var(--ease) both; }

/* ================================================================
   HOMEPAGE HERO v2 — the eye-catching first impression.
   Vibrant light hero, gradient headline, layered floating product art.
   ================================================================ */
.mk-hero2{position:relative;overflow:hidden;border-bottom:1px solid var(--line);
  background:
    radial-gradient(1000px 540px at 80% -10%, var(--accent-tint), transparent 62%),
    radial-gradient(720px 420px at 2% 8%, rgba(46,107,240,.10), transparent 55%),
    var(--paper);}
.mk-hero2__in{position:relative;z-index:2;max-width:1120px;margin:0 auto;
  padding:clamp(36px,6vw,80px) var(--s4) clamp(44px,6vw,88px);
  display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,60px);align-items:center}
@media(max-width:900px){ .mk-hero2__in{grid-template-columns:1fr;text-align:center} .mk-hero2__art{order:-1;margin:0 auto} .mk-hero2__lede,.mk-hero2 h1{margin-left:auto;margin-right:auto} .mk-hero2__cta{justify-content:center} }
.mk-hero2 h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:1.0;
  font-size:clamp(2.5rem,6vw,4.5rem);color:var(--ink);margin:0 0 var(--s4);max-width:15ch}
.mk-grad{background:linear-gradient(100deg,var(--accent-2),#4F46E5 60%,#6D28D9);
  -webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
.mk-hero2__lede{font-size:clamp(1.08rem,1.7vw,1.3rem);color:var(--slate);max-width:46ch;line-height:1.5;margin:0 0 var(--s5)}
.mk-hero2__cta{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.mk-hero2__cta .ds-btn{min-height:52px;font-size:16px;padding:0 26px}
.mk-hero2__trust{margin-top:var(--s4);color:var(--slate-3);font-size:13.5px;font-weight:500}

/* layered product art */
.mk-hero2__art{position:relative;width:100%;max-width:520px}
.mk-hero2__glow{position:absolute;inset:-14% -8%;z-index:0;
  background:radial-gradient(58% 58% at 62% 42%, var(--accent-glow), transparent 72%)}
.mk-stack{position:relative;z-index:1;padding-bottom:26px}
.mk-stack .mk-window{box-shadow:0 34px 70px -26px rgba(16,24,40,.42),0 0 0 1px rgba(16,24,40,.05)}
.mk-stack .mk-phone{position:absolute;right:-3%;bottom:0;width:168px;max-width:42%;margin:0;z-index:2;
  box-shadow:0 34px 64px -20px rgba(16,24,40,.5)}
@media(max-width:520px){ .mk-stack .mk-phone{width:40%;right:-1%} }
@media(prefers-reduced-motion:no-preference){
  .mk-stack{animation:mk-float 6.5s ease-in-out infinite}
  .mk-stack .mk-phone{animation:mk-float 6.5s ease-in-out infinite .9s}
}
@keyframes mk-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}

/* value strip — honest props, punchy, gives the fold some energy */
.mk-vstrip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-sm)}
@media(max-width:720px){ .mk-vstrip{grid-template-columns:repeat(2,1fr)} }
.mk-vstrip>div{background:#fff;padding:var(--s4) var(--s3);text-align:center}
.mk-vstrip b{display:block;font-family:var(--font-display);font-weight:800;font-size:1.55rem;letter-spacing:-.02em;color:var(--accent);line-height:1.1}
.mk-vstrip span{font-size:12.5px;color:var(--slate);font-weight:600;letter-spacing:.01em}

/* ================================================================
   HOMEPAGE HERO v3 — dark, colorful, ANIMATED aurora. More vibe.
   ================================================================ */
.hero3{position:relative;overflow:hidden;background:#0A0E1A;color:#fff;isolation:isolate}
.hero3__aur{position:absolute;inset:0;z-index:0;overflow:hidden}
.hero3__aur i{position:absolute;display:block;border-radius:50%;filter:blur(64px);opacity:.55;mix-blend-mode:screen}
.hero3__aur i:nth-child(1){width:54vw;height:54vw;left:-10%;top:-24%;background:radial-gradient(circle,#2E6BF0,transparent 62%);animation:aur1 17s ease-in-out infinite}
.hero3__aur i:nth-child(2){width:48vw;height:48vw;right:-8%;top:-16%;background:radial-gradient(circle,#8B5CF6,transparent 62%);animation:aur2 21s ease-in-out infinite}
.hero3__aur i:nth-child(3){width:42vw;height:42vw;left:26%;bottom:-34%;background:radial-gradient(circle,#06B6D4,transparent 62%);animation:aur3 19s ease-in-out infinite}
@keyframes aur1{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(9%,11%) scale(1.16)}}
@keyframes aur2{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(-11%,9%) scale(1.12)}}
@keyframes aur3{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(7%,-13%) scale(1.22)}}
.hero3__grid{position:absolute;inset:0;z-index:0;opacity:.12;
  background-image:linear-gradient(rgba(255,255,255,.7) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.7) 1px,transparent 1px);
  background-size:58px 58px;-webkit-mask-image:radial-gradient(circle at 55% 28%,#000,transparent 72%);mask-image:radial-gradient(circle at 55% 28%,#000,transparent 72%)}
.hero3__in{position:relative;z-index:2;max-width:1120px;margin:0 auto;
  padding:clamp(56px,9vw,132px) var(--s4) clamp(56px,8vw,112px);
  display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,60px);align-items:center}
@media(max-width:900px){ .hero3__in{grid-template-columns:1fr;text-align:center} .hero3__art{order:-1;margin:0 auto} .hero3 .lede,.hero3 h1{margin-left:auto;margin-right:auto} .hero3__cta{justify-content:center} }
.hero3 .kicker{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:#fff;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.18);padding:6px 13px;border-radius:var(--r-pill);margin:0 0 var(--s4)}
.hero3 .kicker b{color:#22D3EE}
.hero3 h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:1.0;
  font-size:clamp(2.6rem,6.4vw,4.9rem);margin:0 0 var(--s4);color:#fff;max-width:15ch}
.hero3 .grad{background:linear-gradient(100deg,#60A5FA,#A78BFA 52%,#22D3EE);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
.hero3 .lede{font-size:clamp(1.08rem,1.7vw,1.3rem);color:rgba(255,255,255,.82);max-width:46ch;line-height:1.5;margin:0 0 var(--s5)}
.hero3__cta{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.hero3__cta .ds-btn{min-height:54px;font-size:16px;padding:0 28px}
/* base .ds-btn--ghost now covers the transparent/white-border/no-shadow look;
   this hero only needs its own hover tint on top of that. */
.hero3__cta .ds-btn--ghost:hover{--btn-bg:rgba(255,255,255,.1);--btn-bd:rgba(255,255,255,.6)}
.hero3__trust{margin-top:var(--s4);color:rgba(255,255,255,.55);font-size:13.5px;font-weight:500}
.hero3__art{position:relative;width:100%;max-width:520px}
.hero3__art .mk-window{box-shadow:0 40px 80px -24px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.06)}
.hero3__art .mk-phone{position:absolute;right:-3%;bottom:0;width:168px;max-width:42%;margin:0;z-index:2;box-shadow:0 40px 70px -18px rgba(0,0,0,.65)}
@media(max-width:520px){ .hero3__art .mk-phone{width:40%;right:-1%} }
.hero3__stack{position:relative;padding-bottom:26px}

/* entrance + float + on-scroll reveal (motion, with reduced-motion guard) */
@keyframes hero-in{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
@keyframes mk-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}
.reveal{opacity:0;transform:translateY(26px);transition:opacity .6s var(--ease),transform .6s var(--ease)}
.reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:no-preference){
  .hero3__in>div>*{animation:hero-in .7s var(--ease) both}
  .hero3__in>div>*:nth-child(2){animation-delay:.06s}
  .hero3__in>div>*:nth-child(3){animation-delay:.12s}
  .hero3__in>div>*:nth-child(4){animation-delay:.18s}
  .hero3__art{animation:hero-in .8s var(--ease) both .12s}
  .hero3__stack{animation:mk-float 6.5s ease-in-out infinite}
  .hero3__art .mk-phone{animation:mk-float 6.5s ease-in-out infinite .9s}
}
@media(prefers-reduced-motion:reduce){ .reveal{opacity:1;transform:none} }

/* nav goes transparent while over the dark hero (homepage) */
.mk-nav.on-hero{background:rgba(10,14,26,.72);backdrop-filter:saturate(1.4) blur(14px);-webkit-backdrop-filter:saturate(1.4) blur(14px);border-bottom-color:rgba(255,255,255,.08)}
.mk-nav.on-hero .mk-nav__brand{color:#fff}
.mk-nav.on-hero .mk-nav__brand .mk-nav__mark{box-shadow:0 0 0 1px rgba(255,255,255,.25)}
.mk-nav.on-hero .mk-nav__links a:not(.ds-btn){color:rgba(255,255,255,.82)}
.mk-nav.on-hero .mk-nav__links a:not(.ds-btn):hover{color:#fff;background:rgba(255,255,255,.12)}
.mk-nav.on-hero .ds-btn--secondary{--btn-bg:transparent;--btn-fg:#fff;--btn-bd:rgba(255,255,255,.4);--btn-sh:none}
.mk-nav.on-hero .mk-nav__toggle{background:transparent;border-color:rgba(255,255,255,.32)}
.mk-nav.on-hero .mk-nav__toggle svg{stroke:#fff}

/* ================================================================
   ELEVATION v3 — the craft pass.
   Editorial serif headlines (Fraunces, injected by site-nav.js),
   warm paper canvas, copper accent motif (no more AI-purple),
   real depth on device mockups, mobile air, and the "instinct"
   layer: amber waypoints + a thumb-level action bar on phones.
   ================================================================ */

/* ---- editorial voice: serif display for marketing headlines ---- */
.mk-statement,.mk-h2,.mk-h1,.hero4 h1,.oq__q{
  font-family:"Fraunces",Georgia,"Times New Roman",serif;
  font-weight:600;letter-spacing:-.012em}
.mk-statement em,.mk-h2 em{font-style:italic}

/* ---- warm paper canvas on marketing pages (cool tokens stay in-app) ---- */
body:has(#site-nav){background:#FAF7F1}
body:has(#site-nav) .mk-band{background:#F3EFE6}
body:has(#site-nav) .mk-vstrip{background:#E7E1D4}
body:has(#site-nav) .mk-vstrip>div{background:#FFFDF9}

/* ---- the copper thread: every eyebrow carries the same amber tick,
        so the eye learns "this mark = a new stop on the route" ---- */
.mk-eyebrow{display:inline-flex;align-items:center;gap:10px}
.mk-eyebrow::before{content:"";width:22px;height:2px;border-radius:2px;background:#D9822B;flex:0 0 auto}
.mk-head .mk-eyebrow{justify-content:center}
.mk-eyebrow b{color:#B45309;font-weight:800}

/* ---- device mockups: bezel, glare, layered depth ---- */
.mk-phone{position:relative;background:linear-gradient(180deg,#232E44,#0B1220 60%);
  border-radius:44px;padding:10px;border:1px solid rgba(255,255,255,.10);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),
    0 22px 44px -14px rgba(9,14,28,.42),0 60px 100px -36px rgba(9,14,28,.5)}
.mk-phone::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(118deg,rgba(255,255,255,.14),transparent 34%)}
.mk-phone__screen{background:#FFFFFF;box-shadow:inset 0 0 0 1px rgba(16,24,40,.07)}
.mk-phone__body{background:#F4F6FA}
.mk-window{border-radius:18px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.65),var(--shadow-lg),0 48px 90px -34px rgba(16,24,40,.3)}

/* ---- HERO v4: blueprint navy + copper. Structured, not blobby. ---- */
.hero4{position:relative;overflow:hidden;color:#fff;isolation:isolate;background:
  radial-gradient(900px 480px at 80% 14%,rgba(217,130,43,.16),transparent 56%),
  radial-gradient(760px 560px at 8% 88%,rgba(46,107,240,.17),transparent 62%),
  linear-gradient(180deg,#0C1424,#0A111E)}
.hero4__bp{position:absolute;inset:0;z-index:0;opacity:.5;pointer-events:none;
  background-image:
    linear-gradient(rgba(122,160,255,.075) 1px,transparent 1px),
    linear-gradient(90deg,rgba(122,160,255,.075) 1px,transparent 1px),
    linear-gradient(rgba(122,160,255,.14) 1px,transparent 1px),
    linear-gradient(90deg,rgba(122,160,255,.14) 1px,transparent 1px);
  background-size:26px 26px,26px 26px,130px 130px,130px 130px;
  -webkit-mask-image:radial-gradient(ellipse at 62% 30%,#000 24%,transparent 74%);
  mask-image:radial-gradient(ellipse at 62% 30%,#000 24%,transparent 74%)}
/* ===== hero top banner: ambient brand loop =====
   Reduced opacity + feathered edges so it reads as part of the hero rather than a
   pasted rectangle. The bottom quarter fades and softly blurs into the hero
   background, and the headline is pulled up over that zone so the video
   transitions into the type instead of just occupying space. */
/* MOBILE-FIRST: no visible container at all. The video runs to both page edges
   and straight up to the header, at its own proportions (cover, never stretched).
   Only the bottom is treated: the video itself masks out as it descends and a
   blurred veil rides on top, so it dissolves into the page instead of ending on a
   hard line. */
.hero4__vid{position:relative;z-index:1;max-width:none;margin:0;padding:0}
.hero4__vid-frame{position:relative;border-radius:0;overflow:hidden}
.hero4__vid-el{display:block;width:100%;height:auto;aspect-ratio:4/5;
  object-fit:cover;object-position:center;opacity:.62;pointer-events:none;
  -webkit-mask-image:linear-gradient(180deg,#000 44%,rgba(0,0,0,0) 100%);
          mask-image:linear-gradient(180deg,#000 44%,rgba(0,0,0,0) 100%)}
/* never a play button / control chrome — this is decorative, not a player */
.hero4__vid-el::-webkit-media-controls,
.hero4__vid-el::-webkit-media-controls-panel,
.hero4__vid-el::-webkit-media-controls-start-playback-button,
.hero4__vid-el::-webkit-media-controls-overlay-play-button{display:none!important;-webkit-appearance:none;opacity:0}

/* The dissolve. Deliberately paints NO colour of its own: the blur simply ramps
   in while the video masks itself out, so the bottom resolves into whatever the
   hero background actually is. A painted colour would have to guess that gradient
   and would show as a seam. */
.hero4__vid-fade{position:absolute;left:0;right:0;bottom:0;height:60%;pointer-events:none;
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  -webkit-mask-image:linear-gradient(180deg,rgba(0,0,0,0),#000 58%);
          mask-image:linear-gradient(180deg,rgba(0,0,0,0),#000 58%)}

/* DESKTOP: no video at all — the hero returns to its original composition. */
@media(min-width:760px){
  .hero4__vid{display:none}
}
/* The headline sits ON the dissolving bottom of the video. General sibling (~),
   not adjacent (+): a <script> tag sits between the two elements in the markup.
   Mobile only — the desktop hero has no video, so it keeps its own spacing. */
@media(max-width:759px){
  /* the whole block — kicker, headline, lede, buttons, trust line — rides up
     together, sitting deeper into the video's dissolve */
  .hero4__vid ~ .hero4__in{padding-top:0;margin-top:clamp(-220px,-36vw,-120px)}
  /* the mock console below the trust line earns nothing on a phone */
  .hero4__art{display:none}
}
/* prefers-reduced-motion used to only knock 12% off the opacity (.62 to .5),
   so the autoplaying, looping hero video kept moving exactly as much as
   before. There is no way for a person to pause it themselves: the
   media-controls pseudo-elements above are force-hidden, and the element is
   pointer-events:none by design since it's decorative, so dimming it was
   not a remedy, it just made the same motion slightly fainter. Removing it
   from the layout is the only "stop" this decorative element can offer. */
@media(prefers-reduced-motion:reduce){
  .hero4__vid{display:none}
}
/* The mobile hero pulls its headline up into the video's dissolve zone with
   a negative margin (see .hero4__vid ~ .hero4__in above). With the video
   gone under reduced motion that margin has nothing left to dissolve into
   and would instead pull the headline up over empty space, so both the
   margin and the padding it compensates for are reset to plain top spacing
   here. */
@media(max-width:759px) and (prefers-reduced-motion:reduce){
  .hero4__vid ~ .hero4__in{margin-top:0;padding-top:clamp(56px,9vw,128px)}
}

.hero4__in{position:relative;z-index:2;max-width:1120px;margin:0 auto;
  padding:clamp(56px,9vw,128px) clamp(22px,4vw,24px) clamp(64px,8vw,112px);
  display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(28px,5vw,60px);align-items:center}
@media(max-width:900px){ .hero4__in{grid-template-columns:1fr;text-align:center}
  .hero4__art{order:0;margin:0 auto} .hero4 .lede,.hero4 h1{margin-left:auto;margin-right:auto}
  .hero4__cta{justify-content:center} }
.hero4 .kicker{display:inline-flex;align-items:center;gap:10px;font-size:12px;font-weight:800;
  letter-spacing:.13em;text-transform:uppercase;color:#F0B269;margin:0 0 var(--s4)}
.hero4 .kicker::before{content:"";width:26px;height:2px;background:#D9822B;border-radius:2px}
.hero4 h1{font-weight:600;line-height:1.04;letter-spacing:-.015em;
  font-size:clamp(2.4rem,5.9vw,4.5rem);margin:0 0 var(--s4);color:#fff;max-width:16ch}
.hero4 h1 .hl{font-style:italic;color:#F0B269;
  background:linear-gradient(0deg,rgba(217,130,43,.32),rgba(217,130,43,.32)) no-repeat 0 86%/100% .13em}
.hero4 .lede{font-size:clamp(1.05rem,1.7vw,1.28rem);color:rgba(255,255,255,.82);max-width:46ch;line-height:1.55;margin:0 0 var(--s5)}
.hero4__cta{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.hero4__cta .ds-btn{min-height:54px;font-size:16px;padding:0 28px}
/* base .ds-btn--ghost now covers the transparent/white-border/no-shadow look;
   this hero only needs its own hover tint on top of that. */
.hero4__cta .ds-btn--ghost:hover{--btn-bg:rgba(255,255,255,.1);--btn-bd:rgba(255,255,255,.6)}
.hero4__trust{margin-top:var(--s4);color:rgba(255,255,255,.55);font-size:13.5px;font-weight:500}
.hero4__art{position:relative;width:100%;max-width:520px}
.hero4__art::before{content:"";position:absolute;inset:-8% -6% -2%;z-index:0;border-radius:32px;
  background:radial-gradient(closest-side,rgba(217,130,43,.2),transparent 72%)}
.hero4__art .mk-window{position:relative;z-index:1;transform:rotate(-1.6deg);
  box-shadow:0 44px 90px -26px rgba(0,0,0,.62),0 0 0 1px rgba(255,255,255,.07)}
.hero4__art .mk-phone{position:absolute;right:2px;bottom:0;width:168px;max-width:40%;margin:0;z-index:2;
  transform:rotate(2.4deg)}
.hero4__stack{position:relative;padding-bottom:30px}
.hero4__cue{position:absolute;left:50%;bottom:12px;transform:translateX(-50%);z-index:3;
  display:flex;flex-direction:column;align-items:center;gap:2px;
  color:rgba(255,255,255,.55);font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase}
.hero4__cue:hover{color:rgba(255,255,255,.85)}
.hero4__cue svg{animation:cue-bob 1.9s ease-in-out infinite}
@keyframes cue-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(5px)}}
@media(prefers-reduced-motion:no-preference){
  .hero4__in>div>*{animation:hero-in .7s var(--ease) both}
  .hero4__in>div>*:nth-child(2){animation-delay:.06s}
  .hero4__in>div>*:nth-child(3){animation-delay:.12s}
  .hero4__in>div>*:nth-child(4){animation-delay:.18s}
  .hero4__art{animation:hero-in .8s var(--ease) both .12s}
  .hero4__stack{animation:mk-float 7s ease-in-out infinite}
  .hero4__art .mk-phone{animation:mk-float 7s ease-in-out infinite 1s}
}
@media(max-width:520px){ .hero4__art .mk-phone{width:38%;right:2px} .hero4__cue{display:none} }

/* ---- instinct layer: thumb-level action bar on phones (injected) ---- */
.mk-mcta{position:fixed;left:0;right:0;bottom:0;z-index:80;display:none;gap:10px;
  padding:10px max(16px,env(safe-area-inset-left)) max(12px,env(safe-area-inset-bottom));
  background:rgba(255,253,249,.94);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  border-top:1px solid var(--line);box-shadow:0 -10px 28px -14px rgba(16,24,40,.22);
  transform:translateY(102%);transition:transform .28s var(--ease)}
.mk-mcta .ds-btn{flex:1;min-height:46px;font-size:14.5px}
@media(max-width:760px){ .mk-mcta{display:flex} .mk-mcta.show{transform:none} }

/* ---- mobile air: real side padding, calmer type, less clutter ---- */
@media(max-width:700px){
  .mk-wrap{padding-left:22px;padding-right:22px}
  .mk-section{padding:clamp(40px,10vw,56px) 0}
  .mk-lede{font-size:1.02rem}
  .mk-vstrip{grid-template-columns:1fr 1fr}
  .mk-vstrip>div{padding:16px 10px}
  .mk-vstrip b{font-size:1.3rem}
  .mk-statement{font-size:clamp(1.7rem,7.4vw,2.4rem)}
  .mk-h2{font-size:clamp(1.45rem,6.4vw,2rem)}
  .mk-pain{grid-template-columns:1fr}
}

/* ================================================================
   REFINE v4 — the clean pass. ONE accent (Servora blue), white
   canvas, zero decorative tick marks, surfaces built into the page
   instead of floating on it. Overrides the copper experiment above.
   ================================================================ */

/* white canvas, cool quiet bands */
body:has(#site-nav){background:#fff}
body:has(#site-nav) .mk-band{background:#F5F7FA}
body:has(#site-nav) .mk-vstrip{background:#E8EBF1}
body:has(#site-nav) .mk-vstrip>div{background:#fff}

/* no decorative dashes anywhere — type carries the hierarchy alone */
.mk-eyebrow::before{content:none}
.hero4 .kicker::before{content:none}
.mk-eyebrow{letter-spacing:.14em}
/* --slate-2 is decoration-only (see the :root definition): it fails AA for
   real text, and this bold numeral inside the eyebrow is real text a reader
   needs, not a divider. --slate-3 keeps the same "quiet, secondary" feel
   at ~6:1 on white. */
.mk-eyebrow b{color:var(--slate-3);font-weight:700;font-variant-numeric:tabular-nums;margin-right:2px}

/* hero: blue only, quieter */
.hero4{background:
  radial-gradient(900px 520px at 76% 12%,rgba(46,107,240,.17),transparent 58%),
  linear-gradient(180deg,#0C1424,#0A111E)}
.hero4 .kicker{color:#8FB4FF;letter-spacing:.16em}
.hero4 h1 .hl{font-style:italic;color:#9DC1FF;background:none}
.hero4__art::before{background:radial-gradient(closest-side,rgba(46,107,240,.22),transparent 72%)}

/* services grid: a connected hairline table, not floating cards */
.svcgrid{gap:1px;background:var(--line);border:1px solid var(--line);border-radius:18px;overflow:hidden}
.svgc{border:0;border-radius:0;box-shadow:none}
.svgc::before,.svgc::after{display:none}
.svgc:hover{transform:none;box-shadow:none;background:#F7F9FC;border-color:transparent}

/* the story band: the widget is part of the page, not a box on it */
.mk-dark .psw__stage{box-shadow:none;border:1px solid rgba(255,255,255,.1)}
.mk-dark .psw__q{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.12);color:#fff}
.mk-dark .psw__q:hover{border-color:rgba(255,255,255,.3)}
.mk-dark .psw__q.is-on{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.22);box-shadow:none}
.mk-dark .psw__q__n{color:rgba(255,255,255,.45)}
.mk-dark .psw__q.is-on .psw__q__n{color:#8FB4FF}
.mk-dark .psw__q__t{color:#fff}
.mk-dark .psw__q__tag{background:rgba(255,255,255,.09);color:rgba(255,255,255,.6)}
.mk-dark .psw__q.is-on .psw__q__tag,
.mk-dark .psw__q--svc.is-on .psw__q__tag{background:rgba(46,107,240,.32);color:#BDD4FF}

/* ============================================================================
   MOBILE, WHERE THE WORK ACTUALLY HAPPENS
   ============================================================================
   Everything above this was sized for a desktop and then simply allowed to
   render narrow. On a 375px phone that meant 24px of padding on each side of a
   card (13% of the screen), 48px buttons, 48px empty states and 16px gaps, so
   you could see about a third of any screen at a time.

   That is not a cosmetic problem. A person understands a screen by seeing
   enough of it at once to recognise the shape. Take that away and every screen
   has to be read instead of recognised, which is the difference between
   software that feels obvious and software you have to think about.

   The whole layer works by REDEFINING THE TOKENS. Every component already
   spends --s3, --s4 and --tap, so changing them here re-proportions all 34
   screens at once and none of them can drift apart. No screen code changes.
   ========================================================================= */
@media (max-width: 640px) {
  :root {
    --s1:3px; --s2:6px; --s3:11px; --s4:14px; --s5:20px; --s6:26px; --s7:34px;
    --r-lg:12px; --radius:10px; --r-sm:7px;
    /* 44px is Apple's minimum. Not smaller, ever: this is a gloved thumb. */
    --tap:44px;
    /* .ds-topbar's own min-height drops to 52px in this same breakpoint
       (below). --topbar-h feeds .fs-crumbs' sticky offset; leaving it at
       the desktop 58px here left a 6px band of the page permanently visible
       and scrolling between the topbar and the breadcrumb bar on every
       phone. */
    --topbar-h:52px;
  }

  body{font-size:15px;line-height:1.45}
  h1{font-size:1.22rem;letter-spacing:-.02em}
  h2{font-size:1.04rem}
  h3{font-size:.95rem}

  /* Cards were the biggest offender: padding plus the gap between them ate
     more vertical space than most cards' contents. */
  .ds-card{padding:12px}
  .ds-card+.ds-card{margin-top:8px}
  .fs-body{padding:12px}
  .ds-wrap{padding:12px}

  /* An empty state used 48px of padding to say one sentence. */
  .ds-empty{padding:18px 12px;font-size:13.5px}
  .ds-empty h3{font-size:.95rem}

  .ds-btn{font-size:14px;padding:0 12px}
  /* var(--tap) is 44px in this same breakpoint (redefined above); the
     hardcoded 34px here undercut the "not smaller, ever" tap floor for
     every ds-btn--sm on a phone, including the topbar's Help/Log out and
     the schedule tab's Accept/Decline/Flag row. Density comes back from
     padding and font-size, not height. */
  .ds-btn--sm{min-height:var(--tap);font-size:12.5px;padding:0 10px}
  /* Segmented sub-tab buttons had no mobile override at all and stayed at
     their desktop 36px, also under the floor. */
  .ds-seg button{min-height:var(--tap)}
  /* The shorthand `padding` below used to zero out .ds-select's separate
     40px right-padding (set outside this breakpoint for the chevron), so
     the chevron painted straight over the last few characters of any long
     selected value on every phone. Longhand plus a dedicated select
     override keeps that gutter intact. */
  .ds-input,.ds-select,.ds-textarea{font-size:16px;padding:9px 11px}  /* 16px: iOS zooms below it */
  .ds-select{padding-right:36px}
  /* Four inputs elsewhere in the app don't match .ds-input/.ds-select and so
     never got the 16px floor above: below it, iOS Safari zooms the viewport
     in on focus and does not reliably zoom back out. Worst on
     .svc-nego__input, the one field where a subcontractor types money. */
  .fs-search input,.svc-grid__filter,.svc-sel__input,.svc-nego__input{font-size:16px}
  .fs-search input,.svc-grid__filter{min-height:var(--tap)}
  .ds-label{font-size:12.5px;margin-bottom:4px}
  .ds-chip{font-size:11px;padding:4px 8px}

  /* SQUARES, NOT BARS. minmax(184px) forced one full-width column on a phone,
     so every tile grid became a stack of long rectangles you had to scroll.
     Two up reads as a grid the eye can take in at once. */
  .fs-grid{grid-template-columns:repeat(2,1fr);gap:8px}
  .fs-tile{padding:11px;border-radius:12px}
  .fs-tile__ico{margin-bottom:6px}
  .fs-tile__name{font-size:13px}
  .fs-tile__sub{font-size:11.5px}
  .fs-tile__badge{top:8px;right:8px}

  /* CONTAINMENT. A row of buttons that cannot wrap pushes its last child past
     the edge of the card. Everything in a row may shrink, and may wrap. */
  .ds-row{flex-wrap:wrap;gap:8px}
  .ds-row>*{min-width:0}
  .ds-btn,.ds-chip{max-width:100%}
  .ds-card,.ds-empty,.fs-tile{overflow-wrap:anywhere}

  /* The company name was being crushed by three text buttons beside it. */
  .ds-topbar{padding:8px 12px;min-height:52px;gap:8px}
  .ds-topbar__mark{width:28px;height:28px;border-radius:8px;font-size:13px}
  .ds-topbar__name{font-size:.95rem;min-width:0;flex:1 1 auto}
  .ds-topbar__brand{flex:1 1 auto;min-width:0}

  .fs-crumbs{padding:8px 12px;font-size:12px}
  .ds-stack>*+*{margin-top:8px}
}

/* Very small phones still in use on job sites. */
@media (max-width: 380px) {
  .fs-grid{gap:7px}
  .fs-tile{padding:9px}
  .ds-card{padding:10px}
}

/* ---------------------------------------------------------------------------
   THE APP'S BOTTOM BAR (mobile only)
   .fs__side is display:none below 900px, so on a phone the app had NO
   navigation: the only way to reach any of the twenty-odd tools was to scroll
   the home screen hunting for its tile. That is the whole "I have to jump
   around and I do not know where to start" problem in one line of CSS.
   Five destinations, always one tap away, and More opens the rest GROUPED.
   ------------------------------------------------------------------------- */
.fs-tabs{display:none}
@media (max-width: 899px) {
  .fs-tabs{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;
    background:rgba(255,255,255,.94);backdrop-filter:saturate(1.6) blur(14px);
    -webkit-backdrop-filter:saturate(1.6) blur(14px);
    border-top:1px solid var(--line);
    padding-bottom:env(safe-area-inset-bottom,0)}
  .fs-tabs button{
    flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    background:none;border:0;border-top:2px solid transparent;padding:5px 2px 6px;cursor:pointer;
    font-family:var(--font-ui);font-size:10.5px;font-weight:600;color:var(--slate);
    min-height:52px;letter-spacing:-.01em}
  /* Colour alone (slate to accent blue) sits at about 1.35:1 luminance contrast, which
     reads as identical to a contractor with red-green colour blindness and washes out
     in direct sunlight on a job site. Weight plus a top indicator bar give the active
     tab two more signals that don't depend on distinguishing hue at all. */
  .fs-tabs button[aria-current="page"]{color:var(--accent);font-weight:700;border-top-color:var(--accent)}
  .fs-tabs svg{width:21px;height:21px}
  /* Clear the bar so the last card is never trapped under it. */
  .fs-body{padding-bottom:calc(64px + env(safe-area-inset-bottom,0))}
}

/* ---------------------------------------------------------------------------
   THE MORE SHEET
   Everything else, grouped, so twenty-two flat items become five short lists
   a person can scan. This used to be styled entirely inside the
   max-width:899px query above, but the sheet's presence in the DOM is
   controlled by app.html mounting/unmounting it from the mobile More tab,
   not by CSS. That meant opening it on a tablet in portrait (<900px, tab bar
   showing) and then rotating to landscape (>=900px) left the element
   mounted with no styles at all: a plain, full-width, unbackdropped list of
   buttons stacked under the now-visible desktop sidebar. Living outside the
   query costs nothing on desktop, since desktop never creates a .fs-sheet in
   the first place.
   ------------------------------------------------------------------------- */
.fs-sheet{position:fixed;inset:0;z-index:50;display:flex;align-items:flex-end;
  background:rgba(16,24,40,.42)}
.fs-sheet__in{background:var(--card);width:100%;max-height:82vh;overflow:auto;
  border-radius:18px 18px 0 0;padding:14px 14px calc(20px + env(safe-area-inset-bottom,0))}
.fs-sheet__grip{width:36px;height:4px;border-radius:2px;background:var(--line);margin:0 auto 12px}
/* --slate-2 is decoration-only (see the :root definition): these are the
   "Money / People / Field" group headings, real text a reader has to
   distinguish the sheet's sections by, not a divider. --slate-3 keeps the
   same quiet, secondary weight at ~6:1 on white. */
.fs-sheet__grp{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--slate-3);margin:14px 0 6px}
.fs-sheet__grp:first-of-type{margin-top:0}
.fs-sheet__row{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.fs-sheet__btn{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  background:var(--paper);border:1px solid var(--line);border-radius:12px;padding:11px 6px;
  font-family:var(--font-ui);font-size:11.5px;font-weight:600;color:var(--ink);
  text-align:center;line-height:1.2;cursor:pointer;min-height:66px}
.fs-sheet__btn svg{width:19px;height:19px;color:var(--accent)}

/* ---------------------------------------------------------------------------
   TOPBAR ON A PHONE
   Three text buttons beside the brand left the company name with about eleven
   characters, so "Ridgeline Contracting" read as "Ridgeline C...". The buttons
   are not what you look at when you open the app; the name is. They move into
   the More sheet, and the name gets the width.
   ------------------------------------------------------------------------- */
@media (max-width: 899px) {
  .ds-topbar__actions{display:none}
  .ds-topbar__brand{flex:1 1 100%;min-width:0}
  /* WRAP, DO NOT CHOP. The desktop rule is nowrap + ellipsis, which on a phone
     turns "Ridgeline Contracting & Restoration" into "Ridgeline Contract…".
     A company sees its own name at the top of every screen, and a name that is
     cut off reads as a broken product before anything else has been judged.
     Three lines is the ceiling so a pathological name still cannot push the
     whole page down. Three rather than two because a real one measured here,
     "Northwestern Industrial Mechanical Contractors Incorporated", needs the
     third line and was still being clipped at two. The clamp only engages when
     the text actually needs it, so an ordinary short name stays on one line. */
  .ds-topbar__name{font-size:1rem;white-space:normal;overflow-wrap:anywhere;line-height:1.2;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  /* A three-line name can grow the topbar well past --topbar-h (the name
     above measured to ~74px), but .fs-crumbs was sticking at a fixed
     top:var(--topbar-h) regardless, so the topbar's frosted glass covered
     the top of the breadcrumb bar for any workspace name long enough to
     wrap. Sticky positioning only works when the height of the thing it's
     offset from is known in advance; here it isn't, so the crumbs bar goes
     back into normal flow and simply sits wherever the topbar actually
     ends, however tall that turns out to be. */
  .fs-crumbs{position:static}
}

/* ---------------------------------------------------------------------------
   FIRST-RUN PROMPTS
   Four full cards stacked before any real content is the single biggest reason
   the home screen feels overwhelming: you scroll past the software to reach the
   software. On a phone they become one tight block, with the action inline
   instead of on its own line under a paragraph.
   ------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .ds-prompt{padding:10px 12px}
  .ds-prompt h3{font-size:.9rem;margin:0 0 2px}
  .ds-prompt p{font-size:12.5px;line-height:1.35;margin:0 0 8px}
  /* These buttons are "Finish setup" and "Connect your bank", the two
     actions that gate activation and getting paid, so shrinking them to
     32px was exactly the wrong place to go under the 44px tap floor. */
  .ds-prompt .ds-btn{min-height:var(--tap);font-size:12.5px;padding:0 10px}
  .ds-prompt+.ds-prompt{margin-top:6px}
}

/* The topbar actions carried an inline display:flex, which no stylesheet rule
   can override, so the mobile hide never applied. Declared here instead. */
.ds-topbar__actions{display:flex;gap:6px;flex:0 0 auto}
@media (max-width: 899px){ .ds-topbar__actions{display:none} }

/* ---------------------------------------------------------------------------
   WHAT YOU OPEN THE APP FOR COMES FIRST
   Home appended four first-run prompts before the day's actual work, so on a
   phone you scrolled past Welcome, Finish setup, Connect your bank and a
   checklist to reach "What needs you", which is the thing you open the app to
   see every morning. The prompts do not disappear, they move below it.
   Ordering it here rather than in the render code keeps it a phone concern,
   which is where the problem is: on a desktop all of it fits at once.
   ------------------------------------------------------------------------- */
@media (max-width: 899px) {
  .fs-body{display:flex;flex-direction:column}
  .fs-body>*{order:0;flex:0 0 auto}
  .fs-body>.ds-prompt{order:5}
}

/* A toolbar with a search box and two buttons cannot fit on 375px in one line;
   the input gets crushed to a few characters. The search takes its own line. */
@media (max-width: 640px) {
  .fs-toolbar{flex-wrap:wrap;gap:8px}
  .fs-toolbar h1{flex:1 1 auto;min-width:0}
  .fs-toolbar input[type="search"],.fs-toolbar .ds-input{flex:1 1 100%;order:9;min-width:0}
  .fs-toolbar__spacer{flex:0 0 auto}
}

/* ---------------------------------------------------------------------------
   TOPBAR ON THE OTHER THREE PORTALS
   The crew, sub and client portals carry the contractor's company name beside
   two or three text buttons, so the name was crushed to about eleven
   characters exactly as it was in the app. They have no More sheet to move the
   buttons into, so instead the name is guaranteed most of the row and the
   buttons shrink, wrapping to a second line only if they truly cannot fit.
   Nothing becomes unreachable.
   ------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .ds-topbar{flex-wrap:wrap;row-gap:6px}
  .ds-topbar__brand{flex:1 1 62%;min-width:0}
  /* Help and Log out live here on the crew/sub/client portals with no other
     way to reach them, so 32px undershooting the 44px tap floor hit the
     most frequently tapped controls on the busiest screens. */
  .ds-topbar .ds-btn--sm{padding:0 8px;font-size:12px;min-height:var(--tap)}
  .ds-topbar__name{min-width:0}
}

/* The remove-chip's 44px hit area, kept off the layout so chips do not move. */
.svc-sel__chip-x::after{content:'';position:absolute;inset:-13px}

/* T-CLIENT-35: .ds-hint is used for real warnings AND for neutral "not ready
   yet" notes. The calm modifier stops the neutral ones shouting in amber. */
.ds-hint--calm{color:var(--slate-3);background:var(--neutral-tint)}

/* T-JOBS-18 / T-EST-06: a sticky action bar inside the console sits ON TOP of
   the mobile tab bar below 900px, so the last row of the sheet and the bar you
   need to press are the same 58px of screen. Scoped to .fs-body deliberately:
   the client portal's Sign and Pay bar uses the same class and has no tab bar
   under it, so an unscoped rule would lift that one off the bottom for nothing. */
@media (max-width: 899px){
  .fs-body .ds-sticky-action{bottom:calc(64px + env(safe-area-inset-bottom,0))}
  .fs-back{display:block}
}

/* ============================================================================
   THE DESKTOP LAYER, WHERE THE OTHER HALF OF THE WORK HAPPENS
   ============================================================================
   The block above rebuilt the phone by redefining the tokens. This is its
   mirror image, and it exists because until now there was nothing here at all:
   design.css contained not one min-width query above 900px, so a 27 inch
   monitor rendered the identical 1120px column a 13 inch laptop did. Measured
   on the shipped build, the console's content column used 58% of a 1920px
   screen and 44% of a 2560px one. The rest was page.

   A wider container on its own is not a desktop layout, it is the same phone
   screen stretched, so the width comes with the things that make width worth
   having: a rail you can scan instead of read, list rows at a desktop density,
   dialogs that stop pretending to be bottom sheets, forms that use two columns,
   and a job folder that can show the job AND a section at once.

   THE SPINE
     900px   the rail already appeared here. Grouped navigation, sticky group
             headings, the desktop dialog shape and mouse-sized controls join it.
     1200px  desktop proper. The shell grows, lists take a desktop density,
             forms may go two-column, the job folder may split.
     1600px  large monitor. The shell grows again, the rail widens, the calendar
             and the kanban columns breathe.
     2000px  very large monitor. One last step, and then it STOPS on purpose.
             A 2100px line of body text is not a feature.

   THE NUMBERS, per step. Content measure 1120 → 1240 → 1440 → 1600, beside a
   rail of 250 → 264 → 288 → 300. On a 1920px screen the app now occupies
   1728px where it occupied 1370px; on 2560px, 1900px where it occupied 1370px.
   Both numbers are published as tokens (--app-measure, --rail-w) so the body,
   the breadcrumb bar and the split view track ONE value per step instead of
   three hardcoded ones that drift apart the first time somebody edits one.

   THE PHONE IS UNTOUCHED. Every declaration below lives inside a min-width
   query, so a 390x844 viewport never reads any of it. The two exceptions are
   the pair immediately below, and they are what KEEPS the phone identical
   rather than what changes it.
   ========================================================================= */

/* The only two declarations in this whole layer that sit outside a min-width
   query. Both name classes that appear in NO markup anywhere in the product
   today, so as shipped they match zero elements and move zero pixels. They are
   here because a desktop-only region has to be absent by default and appear at
   a width, never the other way round: the moment the markup lands (see
   .fs-split and .ds-rowhead below) a phone would otherwise be handed a second
   copy of the job's section list, and a column header for columns it is not
   showing. Written as min-width rules that "un-hide" them, the phone renders
   exactly what it renders now both before and after that markup change. */
.fs-split__rail{display:none}
.ds-rowhead{display:none}

/* ---------------------------------------------------------------------------
   900px — THE RAIL EXISTS HERE, SO THIS IS WHERE IT GETS GOOD
   ------------------------------------------------------------------------- */
@media (min-width:900px){
  :root{
    --app-measure:1120px;   /* what the content column is allowed to reach */
    --rail-w:250px;         /* the sidebar beside it */
    --app-gutter:var(--s4); /* the page's own side padding, inside the measure */
    /* .fs-crumbs is 11px of padding twice over one 14px/1.55 line. Anything
       that wants to sit under it and stay put needs that number, and needs it
       to be the same number in both places. */
    --crumbs-h:44px;
    --app-sticky-top:calc(var(--topbar-h) + var(--crumbs-h) + 12px);
  }

  /* ---- the shell ------------------------------------------------------- */
  .fs__side{flex:0 0 var(--rail-w);width:var(--rail-w)}
  .fs-body{max-width:var(--app-measure);padding:var(--app-gutter)}
  /* The breadcrumb bar is full bleed, because it carries the hairline that
     closes the topbar, while .fs-body is a centred column. On any screen wider
     than the measure that meant the crumbs started at the window edge and the
     heading they describe started a hundred pixels further in: the two things
     that name where you are, disagreeing about where the page begins. Padding
     the bar by whatever the centring gap turns out to be lines them up at every
     width without giving up the full-bleed rule. */
  .fs-crumbs{padding-inline:max(var(--app-gutter),calc((100% - var(--app-measure))/2 + var(--app-gutter)))}

  /* ---- THE RAIL -------------------------------------------------------------
     Twenty-one to twenty-four tools under one heading that says "Your
     workspace", then seven jobs under another. Thirty-odd rows of identical
     weight is a list you re-read top to bottom every single time, which is the
     desktop version of exactly the complaint the More sheet fixed on the phone:
     the tools are not missing, nothing tells you where to look.

     The phone already solved this. MORE_GROUPS in app.html sorts the same tools
     into five plain-English groups (Winning work · Doing the work · Getting
     paid · Subcontracting · Your company). The rail should use the same five,
     in the same order, in the same words, so a contractor who learns the shape
     on site already knows it at the desk.

     app.html is locked, so the markup change is written out in the handover
     instead of made here, and the grouped-rail rules below match nothing until
     it lands. What the rail gains TODAY, with no markup change at all, is the
     rest of this section: headings that stop scrolling away, and a density and
     a scrollbar gutter that suit a pointer. */
  .fs__side{padding:12px 10px 28px;scrollbar-gutter:stable}
  /* .fs__side is the scrollport (it is overflow:auto), so a heading pinned to
     its top edge keeps saying which group you are inside however far down the
     thirty rows you have scrolled. Costs nothing before the grouping lands and
     is most of the benefit after it. */
  .fs__grouplabel{position:sticky;top:0;z-index:1;background:#fff}

  /* The grouped rail. <details>/<summary>, so a contractor can fold away the
     groups his trade never opens and the browser keeps the state without a line
     of JavaScript from us. */
  .fs__navgroup>summary{display:flex;align-items:center;gap:8px;cursor:pointer;
    list-style:none;user-select:none;border-radius:var(--r-sm)}
  .fs__navgroup>summary::-webkit-details-marker{display:none}
  .fs__navgroup>summary:hover{color:var(--ink)}
  .fs__navgroup>summary::after{content:"";width:7px;height:7px;margin:0 4px 0 auto;
    border-right:2px solid currentColor;border-bottom:2px solid currentColor;
    transform:translateY(-2px) rotate(45deg);transition:transform .15s var(--ease)}
  .fs__navgroup[open]>summary::after{transform:translateY(1px) rotate(-135deg)}
  /* A folded group still has to say that the thing on screen lives inside it,
     or folding stops being tidying and starts being losing your place. */
  .fs__navgroup:has(.fs__navitem[aria-current="page"])>summary{color:var(--accent)}
  .fs__navgroup>.fs__navitem{padding-left:22px}

  /* ---- DIALOGS STOP BEING BOTTOM SHEETS -------------------------------------
     Four of the five modal call sites in the product ask for --sheet. That is
     the right shape on a phone and the wrong one on a monitor: a 540px panel
     welded to the bottom edge of the window, square across the top, sliding up
     from below the fold, with five hundred pixels of dimmed nothing above it.
     On a desktop a dialog belongs in the middle of the screen at the size of
     its own content.

     The scroll region deliberately stays ON the panel rather than moving to the
     backdrop: the Close button inside every one of these is position:sticky and
     needs the panel to be its scrollport, which is the whole reason it is
     still reachable at the bottom of a long help sheet. */
  .ds-modal-bg--sheet{align-items:center;padding:var(--s5)}
  .ds-modal-bg--sheet .ds-modal{border-radius:var(--r-xl);padding:var(--s5);
    max-height:min(88vh,880px);overflow:auto;animation:ds-pop .22s var(--ease)}
  /* The centred variant never had a height of its own, so a long one ran off
     both ends of the window and its sticky Close bar had no scrollport to stick
     against and simply scrolled away with the content it was meant to let you
     escape. Same panel-scrolls rule, so both variants behave identically here. */
  .ds-modal-bg--center{padding:var(--s5)}
  .ds-modal-bg--center .ds-modal{max-height:min(88vh,880px);overflow:auto}
  .ds-modal{max-width:600px}
}

/* A mouse is not a gloved thumb. --tap is 48px from 641px up, which is correct
   for a touchscreen and heavy on a desktop: it makes every button, input and
   select in the console a fifth taller than it needs to be, and vertical space
   is the thing a list screen is short of. Re-pointing the token inside the two
   containers the app actually renders into re-proportions all of it at once,
   the same way the mobile layer does, and 42px is still well clear of any
   desktop guideline. Gated on pointer:fine so a 1024px tablet keeps 48. */
@media (min-width:900px) and (pointer:fine){
  .fs-body,.ds-modal{--tap:42px}
  /* --sm is a hardcoded 38px, which sits 4px under the new 42 and stops reading
     as a smaller button at all. 34/42 is a size ladder again. */
  .fs-body .ds-btn--sm,.ds-modal .ds-btn--sm{min-height:34px}
}

/* ---------------------------------------------------------------------------
   1200px — DESKTOP PROPER
   ------------------------------------------------------------------------- */
@media (min-width:1200px){
  :root{--app-measure:1240px;--rail-w:264px;--app-gutter:var(--s5)}

  /* A 1.45rem page title is a phone's page title. */
  .fs-toolbar h1{font-size:1.7rem}
  .fs-toolbar{margin-bottom:var(--s5)}
  .fs-search{max-width:440px}

  /* ---- TILES ------------------------------------------------------------
     auto-fill at minmax(184px) is a phone number that never changed: on a
     1656px content row it lays out nine 184px tiles, which is more columns than
     anyone scans and each one still the size it was on a laptop. Fewer, larger
     tiles read as a folder; nine small ones read as confetti. */
  .fs-grid{grid-template-columns:repeat(auto-fill,minmax(212px,1fr));gap:var(--s4)}
  .fs-tile{padding:18px}
  .fs-tile__name{font-size:15px}
  .fs-tile__sub{font-size:13px}
  /* Scoped to the console: .ds-cards is also the marketing homepage's stat row,
     and that page's composition is not this layer's business. */
  .fs-body .ds-cards{grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:var(--s4)}

  /* The empty states are the best writing in the product and they are
     text-align:center, which on a 1376px column throws a two-line sentence
     across the whole screen with the eye starting somewhere different on each
     line. The dashed box keeps the full width, because it is the shape that
     says "this is where the things will be"; only the words inside it get a
     measure. max() hands the width straight back the moment the column is
     narrower than the measure, so nothing changes on a laptop. */
  .fs-body .ds-empty{padding:var(--s6) max(var(--s3),calc((100% - 62ch)/2))}

  /* ---- LISTS: MORE ROWS PER SCREEN -----------------------------------------
     Nearly every list in the app is built the same way and none of them had to
     agree to be: a plain host div holding a stack of .ds-card, each card holding
     exactly one .ds-row with the name on the left and the actions on the right.
     At the desktop card padding (24px) plus the 16px between cards that is
     about 90px per row, so a 1080px screen shows seven clients and then you
     scroll, on a monitor with room for twice that.

     The pattern is recognisable in CSS without touching a single screen file: a
     card whose ONLY child is a .ds-row is a list row, and a card with anything
     else inside it is a content card and keeps its generous padding. 62px a row
     instead of 90 is eleven rows where there were seven.

     .ds-rows is the same thing as an opt-in, for the crew and subcontractor
     portals, which build their lists the same way but do not render into
     .fs-body. Put it on the host div and the rows come with it. */
  .fs-body .ds-card:has(>.ds-row:only-child),
  .ds-rows .ds-card:has(>.ds-row:only-child){padding:13px var(--s4)}
  .fs-body .ds-card:has(>.ds-row:only-child)+.ds-card:has(>.ds-row:only-child),
  .ds-rows .ds-card:has(>.ds-row:only-child)+.ds-card:has(>.ds-row:only-child){margin-top:8px}

  /* ---- REAL COLUMNS, FOR THE LISTS THAT HAVE COLUMNS TO SHOW ---------------
     .ds-row is justify-content:space-between: two blocks, one pinned to each
     end. That is the right shape for a phone and it is exactly why a list of
     invoices on a 1440px screen puts the number at one edge, the amount at the
     other, and nothing whatsoever in between.

     .ds-rowgrid is the opt-in. Add it beside .ds-row, declare the columns once
     in --ds-cols, and the row becomes a real grid on a desktop while staying
     precisely the flex row it is today on a phone, because none of this exists
     below 1200px:

       <div class="ds-rowhead" style="--ds-cols:minmax(0,2fr) 130px 120px auto">
         <span>Invoice</span><span>Sent</span>
         <span class="ds-rowhead__num">Amount</span><span></span></div>
       <div class="ds-card"><div class="ds-row ds-rowgrid"
            style="--ds-cols:minmax(0,2fr) 130px 120px auto"> … </div></div>

     .ds-rowhead is the matching column header and is display:none outside this
     block, so a phone is never shown headings for columns it is not laying out. */
  .ds-rowgrid{display:grid;grid-template-columns:var(--ds-cols,minmax(0,1fr) auto);
    align-items:center;column-gap:var(--s4)}
  .ds-rowgrid>*{min-width:0}
  .ds-rowgrid__num,.ds-rowhead__num{text-align:right;font-variant-numeric:tabular-nums}
  .ds-rowgrid__end{justify-self:end;display:flex;align-items:center;gap:var(--s2)}
  .ds-rowhead{display:grid;grid-template-columns:var(--ds-cols,minmax(0,1fr) auto);
    align-items:center;column-gap:var(--s4);padding:0 var(--s4) 7px;
    font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--slate)}

  /* ---- TABLES ---------------------------------------------------------- */
  .ds-table{font-size:14px}
  .ds-table th{padding:12px 16px;font-size:11.5px}
  .ds-table td{padding:13px 16px}
  /* 70vh is a fraction of the window. What a table actually has to work with is
     whatever is left under the topbar, the crumbs and its own toolbar, so on a
     tall monitor the fraction left a third of the window empty beneath a table
     that was still scrolling. Measuring down from the top spends the height the
     screen really has. */
  .ds-table-wrap{max-height:calc(100vh - var(--app-sticky-top) - 96px)}

  /* ---- THINGS THAT WERE SIZED FOR A NARROW COLUMN ---------------------- */
  .svc-cal__grid{gap:8px}
  .svc-cal__day{min-height:118px}
  .ds-kanban__col,.svc-kb__col{flex:0 0 288px}

  /* ---- FORMS: TWO COLUMNS -------------------------------------------------
     Every form in the product is one column of full-width fields running down
     the middle of the screen, because that is the only shape a phone has. On a
     1920px monitor "Company details" is eight controls in a single stack you
     scroll through, each one stretched to 1190px to hold a five character
     postcode, with a thousand pixels of white page beside it.

     .ds-form2 is the opt-in, and it is opt-in rather than automatic because
     which fields belong side by side is a judgement about the form, not a
     property of the markup. Below 1200px the class does nothing at all and the
     fields stack exactly as they do today.

     WHO SHOULD TAKE IT (in rough order of how much it buys):
       screens/setup.js          company details, trade, address, contact
       screens/portalsettings.js the per-portal toggles and labels
       screens/person.js         a person's name, role, contact, pay
       screens/services.js       a service's name, unit, rate, tax treatment
       screens/clients.js        the client detail form
       screens/gear.js           an item's name, code, owner, condition
       app.html Company & Settings
     A pipeline step that renders three or more .ds-field in one frame is the
     other honest candidate; that one is a change in pipeline.js, not a screen. */
  .ds-form2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:var(--s4);align-items:start}
  .ds-form2>*{min-width:0}
  /* Anything that is not a plain field spans the pair: headings, rules, notes,
     errors, checkboxes, an actions row, and any field carrying a textarea or a
     signature pad, because a scope of work wants the width and a postcode
     does not. */
  .ds-form2>h1,.ds-form2>h2,.ds-form2>h3,.ds-form2>p,.ds-form2>hr,
  .ds-form2>.fs-sec,.ds-form2>.ds-check,.ds-form2>.ds-error,.ds-form2>.ds-note-ok,
  .ds-form2>.ds-hint,.ds-form2>.ds-row,.ds-form2>.ds-sticky-action,
  .ds-form2>.ds-field--full,.ds-form2>.ds-field:has(.ds-textarea),
  .ds-form2>.ds-field:has(.sigpad){grid-column:1/-1}

  /* ---- THE JOB, AND A SECTION, AT THE SAME TIME ---------------------------
     A job folder is a grid of tiles you click into one at a time, and once you
     are inside Photos the job itself is gone: its name, its address, its stage
     and the twelve other sections all left the screen, and the only way back is
     the breadcrumb. That is a phone's bargain, made because a phone has room
     for one thing. A desktop has room for both, and a contractor comparing the
     invoice against the change orders should not be paying a round trip through
     a tile grid for every glance.

     .fs-split is that shape: the job's identity and its section list held still
     in a sticky rail, the section itself in the pane beside it. Below 1200px
     .fs-split is an ordinary div and .fs-split__rail is display:none, so the
     phone renders the section exactly as it does today, full width, with its
     own .fs-back button. Nothing here is a second navigation the phone has to
     carry. The markup change is written out in the handover. */
  .fs-split{display:grid;grid-template-columns:var(--split-w,300px) minmax(0,1fr);
    gap:var(--s5);align-items:start}
  .fs-split__rail{display:block;position:sticky;top:var(--app-sticky-top);
    max-height:calc(100vh - var(--app-sticky-top) - 24px);overflow:auto;
    scrollbar-gutter:stable;min-width:0}
  .fs-split__pane{min-width:0}
  .fs-split__title{font-family:var(--font-display);font-weight:800;font-size:1.15rem;
    letter-spacing:-.015em;line-height:1.2;color:var(--ink);overflow-wrap:anywhere}
  .fs-split__sub{font-size:12.5px;color:var(--slate);line-height:1.35;margin-top:3px}
  .fs-split__nav{display:flex;flex-direction:column;gap:1px;
    margin-top:var(--s3);padding-top:var(--s2);border-top:1px solid var(--line)}
  .fs-split__link{display:flex;align-items:center;gap:10px;width:100%;height:36px;
    padding:0 10px;border:none;background:none;border-radius:var(--r-sm);cursor:pointer;
    text-align:left;font-family:var(--font-ui);font-size:13.5px;font-weight:600;
    color:var(--slate);transition:background .12s,color .12s}
  .fs-split__link:hover{background:var(--paper);color:var(--ink)}
  .fs-split__link[aria-current="page"]{background:var(--accent-tint);color:var(--accent)}
  .fs-split__link svg{flex:0 0 auto}
  .fs-split__count{margin-left:auto;font-size:11px;font-weight:700;color:var(--slate-3)}
  .fs-split__link[aria-current="page"] .fs-split__count{color:var(--accent)}
}

/* The rail's own rows. 40px each is a touch height, and thirty of them is
   1240px of rail against roughly 1020px of usable window on a 1080p screen, so
   the navigation itself needed scrolling before the grouping could help. 34px
   with the type dropped a notch is a desktop rail's height and buys back six
   rows. pointer:fine only, so a touchscreen laptop keeps the taller target. */
@media (min-width:1200px) and (pointer:fine){
  .fs__navitem{height:34px;font-size:13.5px}
  .fs__grouplabel{padding:14px 10px 5px}
}

/* ---------------------------------------------------------------------------
   1600px — A LARGE MONITOR
   ------------------------------------------------------------------------- */
@media (min-width:1600px){
  :root{--app-measure:1440px;--rail-w:288px}
  .fs-grid{grid-template-columns:repeat(auto-fill,minmax(238px,1fr))}
  .fs-body .ds-cards{grid-template-columns:repeat(auto-fit,minmax(232px,1fr))}
  .fs-search{max-width:480px}
  .fs-split{grid-template-columns:var(--split-w,336px) minmax(0,1fr);gap:var(--s6)}
  /* A month at 96px a day was drawn for a 1120px column. Given 1440 it is the
     one screen in the app where more room means more information rather than
     more air: three jobs visible in a cell instead of one and a "+2 more". */
  .svc-cal__day{min-height:142px}
  .ds-kanban__col,.svc-kb__col{flex:0 0 312px}
  .ds-modal{max-width:760px}
  .ds-modal-bg--sheet .ds-modal,.ds-modal-bg--center .ds-modal{max-height:min(86vh,1000px)}
}

/* ---------------------------------------------------------------------------
   2000px — AND THIS IS THE LAST STEP ON PURPOSE
   Past here the measure is frozen at 1600px. The app keeps filling the window
   with rail, gutters and centred page, but a line of body text stops growing,
   because past about 100 characters a line stops being easier to read and
   starts being harder. Growth without a reason is the same mistake as the
   1120px cap, made in the other direction.
   ------------------------------------------------------------------------- */
@media (min-width:2000px){
  :root{--app-measure:1600px;--rail-w:300px;--app-gutter:var(--s6)}
  .fs-grid{grid-template-columns:repeat(auto-fill,minmax(252px,1fr))}
  .fs-split{grid-template-columns:var(--split-w,360px) minmax(0,1fr)}
}
