  *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
  :root{
    --cream:#FAF6EF;
    --cream2:#F2EBDD;
    --cream3:#EDE4D1;
    --gold:#C9A96E;
    --gold-light:#E8D5B0;
    --gold-soft:rgba(201,169,110,0.12);
    --gold-dark:#9B7A42;
    --gold-deep:#7A5E33;
    --charcoal:#2C2825;
    --charcoal2:#4A4540;
    --charcoal3:#6B645E;
    --muted:#9A928C;
    --muted2:#B8B0A8;
    --border:#E5DDD0;
    --border-soft:#EFE8DA;
    --white:#FFFFFF;
    --error:#B83A2C;
    --error-soft:rgba(184,58,44,0.08);
    --success:#2E7D5E;
    --success-soft:rgba(46,125,94,0.10);
    --font-display:'Cormorant Garamond',serif;
    --font-body:'Jost',sans-serif;
    --radius-sm:6px;
    --radius:9px;
    --radius-lg:14px;
    --radius-xl:18px;
    --shadow-xs:0 1px 2px rgba(44,40,37,0.04);
    --shadow:0 1px 3px rgba(44,40,37,0.04),0 4px 16px rgba(44,40,37,0.05);
    --shadow-md:0 2px 6px rgba(44,40,37,0.06),0 12px 32px rgba(44,40,37,0.09);
    --shadow-lg:0 4px 12px rgba(44,40,37,0.08),0 24px 60px rgba(44,40,37,0.16);
    --shadow-gold:0 6px 20px rgba(201,169,110,0.22);
    --ease:cubic-bezier(0.22,1,0.36,1);
    --ease-smooth:cubic-bezier(0.4,0,0.2,1);
  }
  /* height:100lvh (not 100% or 100dvh) is critical on iOS:
     - 100% resolves against the layout viewport, which sits above the home
       indicator — leaves a ~47px strip where the body's cream background
       shows through as a "bar".
     - 100dvh fills the visual viewport but SHRINKS when the keyboard opens,
       and iOS doesn't always restore it cleanly on dismiss — the bar then
       reappears and sticks until reload.
     - 100lvh is the LARGE viewport (UI chrome retracted) and is stable
       across keyboard show/hide, so the body stays full-screen-tall.
     100% kept as a fallback for browsers without lvh support. */
  html,body{height:100%;height:100lvh;background:var(--cream2);color:var(--charcoal);font-family:var(--font-body);font-size:15px;line-height:1.6;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility;-webkit-text-size-adjust:100%;text-size-adjust:100%;overscroll-behavior:none}
  /* Prevent iOS Safari from scrolling the window when an input is focused —
     that scroll shifts position:fixed body up and exposes the html background.
     Scoped to the authed app shell only, so auth/public pages can still scroll
     when the form is taller than the viewport (e.g. the register form on a
     short or narrow web window). */
  html:has(body.app-active){overflow:hidden}
  /* Subtle paper texture on the cream background */
  body::before{content:"";position:fixed;inset:0;pointer-events:none;z-index:0;opacity:0.55;
    background-image:radial-gradient(circle at 18% 22%,rgba(201,169,110,0.05) 0%,transparent 42%),
                     radial-gradient(circle at 82% 78%,rgba(201,169,110,0.035) 0%,transparent 48%);
  }
  #root{position:relative;z-index:1}
  ::selection{background:rgba(201,169,110,0.28);color:var(--charcoal)}
  *:focus-visible{outline:2px solid var(--gold);outline-offset:2px;border-radius:var(--radius-sm)}
  #root{height:100%;display:flex;flex-direction:column;min-height:100vh}
  /* When the authenticated app shell is mounted, lock the document entirely:
     the only scroller is .main. position:fixed stops iOS Safari's whole-page
     rubber-band bounce (overflow:hidden alone doesn't on iOS). Auth/public
     pages keep normal scrolling because they don't get .app-active. */
  /* inset:0 alone (no width/height) stretches the fixed body to the true screen
     edges including the bottom safe area. Adding height:100%/width:100% would
     OVERRIDE inset's bottom:0 — and on iOS a fixed element's height:100% is the
     layout viewport, which stops above the home indicator, leaving the cream
     canvas as a strip. So we deliberately omit them and let inset size it. */
  body.app-active{position:fixed;inset:0;overflow:hidden;overscroll-behavior:none}
  /* #root fills the now-correctly-sized body (top:0+bottom:0 give it a definite
     height, so this % resolves). */
  body.app-active #root{height:100%;min-height:0}
  /* Kill the double-tap-to-zoom gesture and the 300ms tap delay everywhere. */
  body{touch-action:manipulation}

  /* Project pane sticky tab bar. The bar is a child of .main (the scroll
     container). When the user scrolls .main, the topbar above scrolls away
     and this bar pins at top:0. z-index sits above section dividers but
     below modals. */
  .project-tabs-sticky{
    position:sticky;
    top:0;
    z-index:20;
    background:var(--white);
    border-bottom:1px solid var(--border);
    box-shadow:var(--shadow-xs);
  }

  /* AUTH */
  /* ── AUTH SCREEN ──────────────────────────────────────────────────────
     Editorial split-screen: a deep cream "cover panel" on the left with
     a layered architectural arch motif (receding chapel arches in fine
     gold linework), an edition strip, and the brand wordmark; a clean
     ivory form panel on the right. Stacks on mobile. The .auth-wrap-solo
     modifier collapses it back to a single centered card (used for the
     verify-email / pending-approval screens). */
  /* No overflow:hidden on the wrap — the cover has its own overflow:hidden
     to contain the arch decoration, and letting the wrap grow naturally is
     what allows tall content (the register form on short viewports) to push
     the page into a scrollable state instead of being clipped. */
  .auth-wrap{min-height:100vh;display:grid;grid-template-columns:1.05fr 1fr;background:#FFFCF5;position:relative;color:var(--charcoal);flex-shrink:0}
  .auth-wrap-solo{display:flex;align-items:center;justify-content:center;padding:max(32px,calc(env(safe-area-inset-top) + 12px)) 20px max(32px,calc(env(safe-area-inset-bottom) + 12px));background:#FBF5E8}
  .auth-wrap-solo .auth-bg{display:none}

  /* ── LEFT PANEL (the "cover") ─────────────────────────────────────── */
  .auth-cover{position:relative;display:flex;flex-direction:column;justify-content:center;padding:max(48px,calc(env(safe-area-inset-top) + 16px)) 56px 48px;overflow:hidden;
    background:
      radial-gradient(ellipse 80% 60% at 12% 10%, rgba(255,250,235,0.85) 0%, transparent 55%),
      radial-gradient(ellipse 100% 80% at 85% 90%, rgba(155,122,66,0.18) 0%, transparent 60%),
      linear-gradient(155deg, #F4E8CE 0%, #E8D5B0 38%, #D9BE8A 100%);
  }
  /* Soft grain so the gradient doesn't read as flat AI candy */
  .auth-cover::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:0.18;mix-blend-mode:multiply;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.55  0 0 0 0 0.45  0 0 0 0 0.28  0 0 0 0.55 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  }
  /* Receding chapel arches — fine gold linework, breathing slowly. */
  .auth-cover::after{content:"";position:absolute;right:-40px;bottom:-20px;width:620px;height:620px;pointer-events:none;opacity:0.6;transform-origin:50% 100%;
    background:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400' fill='none' stroke='%239B7A42' stroke-width='1' stroke-linecap='round' stroke-linejoin='round'><path d='M30 380 H370' opacity='0.55'/><path d='M70 380 V130 A130 130 0 0 1 330 130 V380' opacity='0.95'/><path d='M58 130 H82' opacity='0.7'/><path d='M318 130 H342' opacity='0.7'/><path d='M108 380 V165 A92 92 0 0 1 292 165 V380' opacity='0.7'/><path d='M98 165 H118' opacity='0.55'/><path d='M282 165 H302' opacity='0.55'/><path d='M145 380 V198 A55 55 0 0 1 255 198 V380' opacity='0.5'/><path d='M178 380 V222 A22 22 0 0 1 222 222 V380' opacity='0.38'/><circle cx='200' cy='245' r='52' opacity='0.14'/><circle cx='200' cy='245' r='32' opacity='0.2'/><circle cx='200' cy='130' r='3.4' fill='%239B7A42' stroke='none'/><circle cx='200' cy='165' r='2.6' fill='%23C9A96E' stroke='none'/><circle cx='200' cy='198' r='2' fill='%239B7A42' stroke='none'/><circle cx='200' cy='222' r='1.5' fill='%23C9A96E' stroke='none'/></svg>") center/contain no-repeat;
    animation:authDrift 14s ease-in-out infinite alternate;
  }
  @keyframes authDrift{from{transform:translateY(0) scale(1);opacity:0.55}to{transform:translateY(-6px) scale(1.015);opacity:0.68}}

  /* Brand wordmark + tagline in the middle of the cover */
  .auth-cover-brand{position:relative;z-index:2;max-width:520px}
  .auth-cover-eyebrow{font-size:11px;letter-spacing:0.34em;text-transform:uppercase;color:var(--gold-deep);font-weight:600;margin-bottom:18px;display:inline-flex;align-items:center;gap:12px}
  .auth-cover-eyebrow::before{content:"";width:22px;height:1px;background:var(--gold-dark)}
  .auth-cover-title{font-family:var(--font-display);font-style:italic;font-weight:300;font-size:clamp(54px,7.4vw,96px);line-height:0.96;letter-spacing:-0.01em;color:var(--charcoal);margin:0 0 22px}
  .auth-cover-title .amp{font-family:var(--font-display);color:var(--gold-dark);font-style:italic;font-weight:400}
  .auth-cover-tag{font-family:var(--font-display);font-style:italic;font-size:clamp(20px,1.9vw,26px);line-height:1.45;color:var(--charcoal2);max-width:440px;font-weight:400;margin:0}
  .auth-cover-tag::after{content:"";display:block;width:64px;height:1px;background:var(--gold-dark);margin-top:22px;opacity:0.6}

  /* ── RIGHT PANEL (the form) ──────────────────────────────────────── */
  /* align-items:safe center keeps the card vertically centered when it
     fits, but falls back to flex-start when the card is taller than the
     panel — preventing the top of the register form from getting clipped
     above the scroll position on short viewports. */
  .auth-panel{position:relative;display:flex;align-items:safe center;justify-content:center;padding:48px 56px;background:#FFFCF5;
    background-image:
      radial-gradient(circle at 100% 0%, rgba(201,169,110,0.10) 0%, transparent 45%),
      radial-gradient(circle at 0% 100%, rgba(201,169,110,0.07) 0%, transparent 40%);
  }
  /* Thin gold seam where the two panels meet */
  .auth-panel::before{content:"";position:absolute;top:8%;bottom:8%;left:0;width:1px;background:linear-gradient(180deg,transparent,rgba(201,169,110,0.45) 25%,rgba(201,169,110,0.45) 75%,transparent)}
  .auth-card{background:transparent;border:none;border-radius:0;padding:0;width:100%;max-width:420px;position:relative;box-shadow:none;animation:authRise .7s var(--ease-smooth) both}
  /* Solo (verify/pending) restores the card chrome */
  .auth-wrap-solo .auth-card{background:#FFFEFB;border:1px solid rgba(201,169,110,0.25);border-radius:var(--radius-xl);padding:52px 44px 40px;max-width:460px;
    box-shadow:0 1px 2px rgba(155,122,66,0.06),0 12px 32px rgba(155,122,66,0.10),0 30px 80px rgba(44,40,37,0.10)}
  .auth-wrap-solo .auth-card::before{content:"";position:absolute;top:0;left:32px;right:32px;height:1px;background:linear-gradient(90deg,transparent,var(--gold) 30%,var(--gold) 70%,transparent)}

  @keyframes authRise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

  /* Welcome header above the tabs */
  .auth-welcome{margin-bottom:30px}
  .auth-welcome-eyebrow{font-size:10px;letter-spacing:0.32em;text-transform:uppercase;color:var(--gold-dark);font-weight:600;margin-bottom:14px;display:flex;align-items:center;gap:10px}
  .auth-welcome-eyebrow::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,var(--gold-light),transparent)}
  .auth-welcome-title{font-family:var(--font-display);font-style:italic;font-weight:300;font-size:38px;line-height:1.05;color:var(--charcoal);margin:0 0 8px}
  .auth-welcome-sub{font-size:13px;color:var(--charcoal3);line-height:1.6;max-width:340px}

  /* Solo-screen logo (verify/pending) keeps its centered ornament */
  .auth-wrap-solo .auth-logo{text-align:center;margin-bottom:28px;position:relative}
  .auth-wrap-solo .auth-logo::before{content:"";display:block;width:28px;height:28px;margin:0 auto 14px;opacity:0.7;
    background:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none' stroke='%23C9A96E' stroke-width='1.1' stroke-linecap='round'><circle cx='16' cy='10' r='3'/><circle cx='10' cy='16' r='3'/><circle cx='22' cy='16' r='3'/><circle cx='16' cy='22' r='3'/><circle cx='16' cy='16' r='1.6' fill='%23C9A96E' stroke='none'/></svg>") center/contain no-repeat}
  .auth-wrap-solo .auth-logo::after{content:"";display:block;width:44px;height:1px;background:linear-gradient(90deg,transparent,var(--gold),transparent);margin:18px auto 0}
  .auth-logo-title{font-family:var(--font-display);font-size:44px;font-weight:300;letter-spacing:0.04em;color:var(--charcoal);line-height:1.05;font-style:italic}
  .auth-logo-sub{font-size:10px;letter-spacing:0.32em;text-transform:uppercase;color:var(--gold-dark);margin-top:10px;font-weight:500}

  /* Tabs — slimmer, with a moving underline rather than a charcoal pill */
  .tab-row{display:flex;gap:28px;margin-bottom:26px;position:relative;border-bottom:1px solid rgba(201,169,110,0.25);padding:0 2px}
  .tab-btn{flex:0 0 auto;padding:12px 2px;background:transparent;border:none;cursor:pointer;font-family:var(--font-body);font-size:11px;letter-spacing:0.2em;text-transform:uppercase;color:var(--charcoal3);transition:color .2s var(--ease-smooth);font-weight:500;position:relative}
  .tab-btn::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--charcoal);transform:scaleX(0);transform-origin:left center;transition:transform .35s var(--ease-smooth)}
  .tab-btn:hover{color:var(--charcoal2)}
  .tab-btn.active{color:var(--charcoal)}
  .tab-btn.active::after{transform:scaleX(1)}

  /* Inputs inside the form panel — bigger, more confident */
  .auth-card .field{margin-bottom:18px}
  .auth-card .field label{color:var(--charcoal3);letter-spacing:0.22em;font-size:10px}
  .auth-card .field input{background:#FFFEFB;border:1px solid rgba(201,169,110,0.30);padding:14px 16px;font-size:14px;border-radius:var(--radius)}
  .auth-card .field input:hover{border-color:var(--gold-light);background:#FFFFFF}
  .auth-card .field input:focus{border-color:var(--gold);box-shadow:0 0 0 4px rgba(201,169,110,0.18);background:#FFFFFF}

  /* The primary button gets a gold underline reveal on hover */
  .auth-card .btn-primary{padding:14px 24px;font-size:11px;letter-spacing:0.22em;position:relative;overflow:hidden}
  .auth-card .btn-primary::after{content:"";position:absolute;left:50%;bottom:6px;width:0;height:1px;background:var(--gold-light);transition:width .35s var(--ease-smooth),left .35s var(--ease-smooth)}
  .auth-card .btn-primary:hover::after{width:32px;left:calc(50% - 16px)}

  .auth-divider{display:flex;align-items:center;gap:12px;margin:20px 0}
  .auth-divider span{height:1px;flex:1;background:var(--border)}
  .auth-divider p{font-size:10px;color:var(--muted);letter-spacing:0.18em;text-transform:uppercase}

  /* Bottom footer note */
  .auth-foot{margin-top:34px;font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:var(--charcoal3);font-weight:500;display:flex;align-items:center;gap:14px}
  .auth-foot::before{content:"";flex:1;height:1px;background:linear-gradient(90deg,transparent,rgba(201,169,110,0.4))}
  .auth-foot::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,rgba(201,169,110,0.4),transparent)}

  /* ── RESPONSIVE: stack the cover on top of the form on narrow screens.
       On mobile we abandon the flex column + justify-content:space-between
       layout (which fights against natural sizing when content > min-height
       and tends to clip with overflow:hidden) and switch to a plain block
       flow with margins. Content always grows the cover; the botanical
       ::after decoration is still clipped to cover bounds by overflow. */
  @media (max-width:960px){
    /* Flex column on mobile: cover at its natural height up top, panel
       grows to fill whatever's left in the viewport. The card centers
       inside that flexed panel so a short form (Sign in) doesn't leave a
       cream gap below — and a tall form (Register) just pushes the wrap
       past 100vh and the body scrolls. */
    .auth-wrap{display:flex;flex-direction:column;min-height:100vh;grid-template-columns:none;grid-template-rows:none;overflow:visible}
    .auth-cover{display:block;flex:0 0 auto;min-height:0;padding:max(24px,calc(env(safe-area-inset-top) + 8px)) 28px 18px}
    .auth-cover-brand{margin:0 0 14px}
    .auth-cover-title{font-size:clamp(28px,6vw,38px);margin:0 0 10px;line-height:1}
    .auth-cover-tag{font-size:clamp(13px,1.7vw,15px);max-width:100%;line-height:1.4}
    .auth-cover-tag::after{display:none}
    .auth-cover::after{width:200px;height:200px;right:-16px;bottom:-4px;opacity:0.4}
    .auth-panel{flex:1 1 auto;padding:18px 24px 20px;display:flex;align-items:flex-start;justify-content:center}
    .auth-panel::before{display:none}
    .auth-card{max-width:460px}
    /* On mobile the cover headline already greets the user — the in-form
       welcome block is redundant and burns ~120px of vertical. Hide it. */
    .auth-welcome{display:none}
    .tab-row{margin-bottom:16px}
    .auth-card .field{margin-bottom:12px}
    .auth-foot{margin-top:18px}
  }
  @media (max-width:560px){
    .auth-cover{padding:max(20px,calc(env(safe-area-inset-top) + 6px)) 22px 14px}
    .auth-cover-brand{margin:0 0 10px}
    .auth-cover-eyebrow{margin-bottom:10px;font-size:10px;letter-spacing:0.3em}
    .auth-cover-title{font-size:clamp(24px,6.8vw,32px);margin:0 0 8px;line-height:1}
    .auth-cover-tag{font-size:13px;line-height:1.35}
    .auth-cover::after{width:160px;height:160px;right:-10px;bottom:-2px;opacity:0.38}
    .auth-panel{padding:14px 22px 16px}
    .auth-card .field{margin-bottom:10px}
    .tab-row{margin-bottom:14px;gap:20px}
    .auth-foot{margin-top:14px;font-size:9px;letter-spacing:0.18em}
  }
  .field{margin-bottom:18px}
  .field label{display:block;font-size:10px;letter-spacing:0.16em;text-transform:uppercase;color:var(--muted);margin-bottom:7px;font-weight:500}
  .field input,.field select,.field textarea{width:100%;padding:12px 14px;border:1px solid var(--border);border-radius:var(--radius);font-family:var(--font-body);font-size:14px;color:var(--charcoal);background:var(--white);outline:none;transition:border-color .2s var(--ease-smooth),box-shadow .2s var(--ease-smooth),background .2s var(--ease-smooth)}
  .field input:hover,.field select:hover,.field textarea:hover{border-color:var(--gold-light)}
  .field input:focus,.field select:focus,.field textarea:focus{border-color:var(--gold);box-shadow:0 0 0 3px var(--gold-soft);outline:none}
  .field input::placeholder,.field textarea::placeholder{color:var(--muted2)}
  .btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:12px 24px;border-radius:var(--radius);font-family:var(--font-body);font-size:12px;letter-spacing:0.14em;text-transform:uppercase;cursor:pointer;border:none;transition:transform .15s var(--ease-smooth),background .2s var(--ease-smooth),color .2s var(--ease-smooth),border-color .2s var(--ease-smooth),box-shadow .2s var(--ease-smooth);font-weight:500;line-height:1;-webkit-tap-highlight-color:transparent;position:relative}
  .btn:hover{transform:translateY(-1px)}
  .btn:active{transform:translateY(0)}
  .btn-primary{background:var(--charcoal);color:var(--white);box-shadow:0 1px 2px rgba(44,40,37,0.08),0 4px 12px rgba(44,40,37,0.12)}
  .btn-primary:hover{background:var(--charcoal2);box-shadow:0 2px 4px rgba(44,40,37,0.10),0 8px 20px rgba(44,40,37,0.18)}
  .btn-gold{background:var(--gold);color:var(--white);box-shadow:0 1px 2px rgba(155,122,66,0.10),0 4px 12px rgba(201,169,110,0.28)}
  .btn-gold:hover{background:var(--gold-dark);box-shadow:0 2px 4px rgba(155,122,66,0.14),var(--shadow-gold)}
  .btn-outline{background:var(--white);color:var(--charcoal);border:1px solid var(--border);box-shadow:var(--shadow-xs)}
  .btn-outline:hover{border-color:var(--charcoal);background:var(--white);box-shadow:0 2px 8px rgba(44,40,37,0.06)}
  .btn-danger{background:transparent;color:var(--error);border:1px solid var(--error)}
  .btn-danger:hover{background:var(--error);color:var(--white);box-shadow:0 4px 12px rgba(184,58,44,0.22)}
  .btn-full{width:100%}
  .btn:disabled{opacity:0.5;cursor:not-allowed;transform:none!important}
  .btn:disabled:hover{transform:none;box-shadow:var(--shadow-xs)}
  .err{color:var(--error);font-size:12px;margin-top:8px}
  .ok{color:var(--success);font-size:12px;margin-top:8px}

  /* APP SHELL */
  .app{display:flex;height:100vh;height:100dvh;height:100%;overflow:hidden}
  .sidebar{width:244px;min-width:244px;background:var(--charcoal);background-image:linear-gradient(180deg,#312D2A 0%,#2C2825 38%,#272320 100%);display:flex;flex-direction:column;padding:0;height:100vh;overflow-y:auto;flex-shrink:0;position:relative}
  /* Right-edge gold hairline for depth */
  .sidebar::after{content:"";position:absolute;top:0;bottom:0;right:0;width:1px;background:linear-gradient(180deg,transparent,rgba(201,169,110,0.18) 30%,rgba(201,169,110,0.18) 70%,transparent)}
  .sidebar::-webkit-scrollbar{width:6px}
  .sidebar::-webkit-scrollbar-track{background:transparent}
  .sidebar::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.08);border-radius:3px}
  .sidebar-logo{padding:30px 24px 22px;border-bottom:1px solid rgba(255,255,255,0.07);position:relative}
  .sidebar-logo::after{content:"";position:absolute;bottom:-1px;left:24px;width:32px;height:1px;background:var(--gold);opacity:0.7}
  .sidebar-logo-title{font-family:var(--font-display);font-size:27px;font-weight:300;letter-spacing:0.07em;color:var(--white);line-height:1.1}
  .sidebar-logo-sub{font-size:10px;letter-spacing:0.22em;text-transform:uppercase;color:var(--gold);margin-top:4px;font-weight:500}
  .sidebar-section{padding:22px 0 8px}
  .sidebar-section-label{font-size:10px;letter-spacing:0.2em;text-transform:uppercase;color:rgba(255,255,255,0.32);padding:0 24px;margin-bottom:8px;font-weight:500}
  .nav-item{display:flex;align-items:center;gap:11px;padding:11px 22px;cursor:pointer;color:rgba(255,255,255,0.62);font-size:13px;letter-spacing:0.04em;transition:color .2s var(--ease-smooth),background .2s var(--ease-smooth);border-left:2px solid transparent;position:relative}
  .nav-item:hover{color:var(--white);background:rgba(255,255,255,0.04)}
  .nav-item.active{color:var(--white);background:linear-gradient(90deg,rgba(201,169,110,0.18) 0%,rgba(201,169,110,0.04) 100%);border-left-color:var(--gold)}
  .nav-item.active::before{content:"";position:absolute;left:-2px;top:50%;transform:translateY(-50%);width:2px;height:60%;background:var(--gold);box-shadow:0 0 12px rgba(201,169,110,0.6)}
  .nav-item svg{width:16px;height:16px;flex-shrink:0;opacity:0.85}
  .nav-item.active svg{opacity:1}
  .sidebar-footer{margin-top:auto;padding:18px 16px;border-top:1px solid rgba(255,255,255,0.07);background:rgba(0,0,0,0.10)}
  /* When a bottom nav section sits above the footer, the section handles the
     push-to-bottom and the footer just sits flush under it. */
  .sidebar-section-bottom + .sidebar-footer{margin-top:0}
  .user-chip{display:flex;align-items:center;gap:10px}
  .user-avatar{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--gold) 0%,var(--gold-dark) 100%);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;color:var(--white);flex-shrink:0;letter-spacing:0.04em;box-shadow:0 2px 8px rgba(201,169,110,0.25)}
  .user-info{flex:1;min-width:0;overflow:hidden}
  .user-name{font-size:12px;color:var(--white);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .user-role{font-size:9px;color:rgba(255,255,255,0.45);letter-spacing:0.16em;text-transform:uppercase;margin-top:2px;font-weight:500}
  .logout-btn{display:flex;align-items:center;gap:5px;background:transparent;border:1px solid rgba(255,255,255,0.14);border-radius:var(--radius-sm);cursor:pointer;color:rgba(255,255,255,0.55);transition:color .2s,border-color .2s,background .2s;padding:6px 9px;font-family:var(--font-body);font-size:10px;letter-spacing:0.12em;text-transform:uppercase;font-weight:500;flex-shrink:0}
  .logout-btn svg{width:12px;height:12px}
  .logout-btn:hover{color:var(--white);border-color:rgba(201,169,110,0.4);background:rgba(201,169,110,0.10)}
  /* Icon-only variant — used in the sidebar footer so long user names don't
     get crowded against the button. The label collapses to a tooltip. */
  .logout-btn-icon{padding:7px;width:30px;height:30px;justify-content:center;gap:0}
  .logout-btn-icon svg{width:13px;height:13px}
  /* Sidebar badge in nav-item labels */
  .nav-item span[style*="background:var(--gold)"]{background:var(--gold)!important;color:#fff;border-radius:20px;font-size:9px;padding:2px 8px;margin-left:6px;letter-spacing:0.06em;font-weight:600;box-shadow:0 1px 3px rgba(201,169,110,0.4)}

  /* Bottom section: same nav-item styling as the top, just anchored to the
     bottom of the sidebar with a subtle separator. Used for rarely-touched
     items (Service Catalog, Contractors, Settings). */
  .sidebar-section-bottom{margin-top:auto;padding-top:14px;padding-bottom:6px;border-top:1px solid rgba(255,255,255,0.07);position:relative}
  .sidebar-section-bottom::before{content:"";position:absolute;top:-1px;left:24px;width:32px;height:1px;background:var(--gold);opacity:0.4}

  /* ── Sidebar section labels (WORK / STUDIO) ─────────────────────────────
     A small all-caps label that sits above each nav group. Gives the sparse
     sidebar visual rhythm and tells the user the two groups are conceptually
     different — "things in flight" vs "studio configuration". The label uses
     the same gold-on-charcoal palette as the brand mark above. */
  .sidebar-group-label{
    font-size:9px;
    letter-spacing:0.28em;
    text-transform:uppercase;
    color:rgba(201,169,110,0.55);
    padding:0 24px;
    margin:0 0 10px;
    font-weight:600;
    display:flex;
    align-items:center;
    gap:10px;
  }
  .sidebar-group-label::after{
    content:"";
    flex:1;
    height:1px;
    background:linear-gradient(90deg,rgba(201,169,110,0.18),transparent);
  }
  /* Tighter top padding on sections that have a label — the label takes
     the visual weight, so the section doesn't need its own gap above. */
  .sidebar-section.sidebar-section-labeled{padding-top:18px}
  .sidebar-section-bottom .sidebar-group-label{margin-top:2px}

  /* Subtle hover lift on the gold accent for active items — the existing
     left-border already pulses; add a faint right-side glow to make the
     active row feel "lit". Strictly decorative; doesn't change layout. */
  .nav-item.active::after{
    content:"";
    position:absolute;
    top:0;bottom:0;right:0;
    width:24px;
    background:radial-gradient(ellipse at right,rgba(201,169,110,0.10),transparent 70%);
    pointer-events:none;
  }

  /* Badge polish — pulled out of the inline span style so it lives in CSS.
     Used for pending-count chips next to nav labels. Sized to feel like a
     proper count badge (circle for single digits, soft pill for multi-digit)
     and right-anchored across every nav item via margin-left:auto. */
  .sidebar-badge{
    background:var(--gold);
    color:#fff;
    border-radius:999px;
    font-size:11px;
    min-width:20px;
    height:20px;
    padding:0 7px;
    margin-left:auto;
    letter-spacing:0.02em;
    font-weight:600;
    line-height:20px;
    text-align:center;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    box-sizing:border-box;
  }
  .nav-item .sidebar-badge{margin-left:auto}
  /* Disputed/error variant — same shape, red instead of gold. */
  .sidebar-badge.sidebar-badge-err{background:var(--error)}

  /* MAIN */
  /* viewport-fit=cover lets content run edge-to-edge under the home indicator,
     matching native iOS apps. No bottom safe-area reservation here — that
     reads as an out-of-place cream band against white content cards. */
  .main{flex:1;display:flex;flex-direction:column;min-width:0;overflow-y:auto;overflow-x:hidden;height:100%;background:var(--cream2);-webkit-overflow-scrolling:touch;overscroll-behavior:none}
  .main::-webkit-scrollbar{width:8px}
  .main::-webkit-scrollbar-track{background:transparent}
  .main::-webkit-scrollbar-thumb{background:rgba(44,40,37,0.10);border-radius:4px}
  .main::-webkit-scrollbar-thumb:hover{background:rgba(44,40,37,0.18)}
  .topbar{padding:calc(22px + env(safe-area-inset-top)) 32px 22px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:flex-start;background:var(--white);position:sticky;top:0;z-index:10;gap:16px}
  .topbar > *:last-child:not(:nth-child(-n+2)){margin-left:auto}
  .topbar-title{font-family:var(--font-display);font-size:30px;font-weight:300;letter-spacing:0.015em;line-height:1.25;padding-bottom:2px}
  /* Grouped topbar action buttons — right-aligned on desktop. On mobile they
     drop to their own full-width row (see media query) so the title + hamburger
     stay clean on the first row. */
  .topbar-actions{display:flex;gap:8px;align-items:center;margin-left:auto;flex-wrap:wrap}
  /* Filter chip row (e.g. contractor Invoices: All / Pending / Approved / Paid).
     Compact pills — far less horizontal padding than a full .btn so the row
     reads as filters, not primary actions, and fits more per line on a phone. */
  .filter-pills{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:20px}
  /* Compact horizontally so 5+ pills fit one row at 390px, tall vertically
     so the hit area still clears the 44px iOS minimum. min-height takes care
     of the touch spec without growing the pill's width. */
  .filter-pill{padding:12px 12px;font-size:11px;letter-spacing:0.08em;min-height:44px}
  .topbar-sub{font-size:12px;color:var(--muted);margin-top:3px;letter-spacing:0.02em}
  .page{padding:30px 32px 48px;animation:fadeIn .4s var(--ease) both}

  /* CARDS & STATS */
  .stats-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px;margin-bottom:30px}
  .stat-card{background:var(--white);border:1px solid var(--border);border-radius:var(--radius-lg);padding:22px 24px;position:relative;overflow:hidden;transition:transform .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease);box-shadow:var(--shadow-xs)}
  .stat-card::before{content:"";position:absolute;left:0;bottom:0;height:2px;width:0;background:linear-gradient(90deg,var(--gold),var(--gold-light));transition:width .4s var(--ease)}
  .stat-card:hover{transform:translateY(-2px);box-shadow:var(--shadow);border-color:var(--gold-light)}
  .stat-card:hover::before{width:100%}
  .stat-label{font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--muted);margin-bottom:8px;font-weight:500}
  .stat-value{font-family:var(--font-display);font-size:36px;font-weight:300;color:var(--charcoal);line-height:1;letter-spacing:0.01em}
  .stat-sub{font-size:11px;color:var(--muted);margin-top:6px;letter-spacing:0.04em}

  .card{background:var(--white);border:1px solid var(--border);border-radius:var(--radius-lg);padding:26px;margin-bottom:20px;box-shadow:var(--shadow);position:relative;transition:box-shadow .25s var(--ease)}
  .card:hover{box-shadow:var(--shadow-md)}
  .card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:22px;gap:16px;flex-wrap:wrap}
  /* Card titles use the body font for daily scanning calm — display font is
     reserved for "moments" (page h1, modal titles, empty states, stat values
     and other large display numerics). */
  .card-title{font-family:var(--font-body);font-size:17px;font-weight:600;letter-spacing:0.005em;color:var(--charcoal);line-height:1.25}
  .card-sub{font-size:12px;color:var(--muted);margin-top:3px;letter-spacing:0.02em}

  /* Project pane section cards — white capsules matching the dashboard's
     stat cards. The page is cream1, sections are white (one tier up), and
     inset/sub-card surfaces inside use cream tints to create depth downward.
     Resets the legacy accordion inset on the panel's own wrapper so it sits
     flush inside the section. */
  .proj-section{background:var(--white);border:1px solid var(--border);border-radius:var(--radius-lg);padding:24px 26px;margin-bottom:18px;box-shadow:var(--shadow);position:relative;transition:box-shadow .25s var(--ease)}
  .proj-section:hover{box-shadow:var(--shadow-md)}

  /* ── Projects view toggle (List | Calendar) ─────────────────────────────
     Two-pill toggle that flips Projects between list and calendar lenses.
     Same data, two ways to look at it. Visually distinct from the status
     filters below (gold accent, inset shadow on the active pill) so users
     understand this is a layout switch, not just another filter. */
  .proj-view-toggle{
    display:inline-flex;
    background:var(--cream2);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:3px;
    gap:2px;
    box-shadow:var(--shadow-xs) inset;
  }
  .proj-view-btn{
    display:inline-flex;
    align-items:center;
    gap:7px;
    padding:11px 14px;
    min-height:40px;
    border:none;
    background:transparent;
    border-radius:6px;
    cursor:pointer;
    font-family:var(--font-body);
    font-size:12px;
    font-weight:500;
    letter-spacing:0.04em;
    color:var(--charcoal3);
    transition:color .15s,background .15s,box-shadow .15s;
  }
  .proj-view-btn:hover{color:var(--charcoal)}
  .proj-view-btn.active{
    background:var(--white);
    color:var(--charcoal);
    box-shadow:var(--shadow-xs), 0 0 0 1px rgba(201,169,110,0.25);
  }
  .proj-view-btn.active svg{stroke:var(--gold-dark)}
  .proj-view-btn svg{opacity:0.75}

  /* ── Books page tabs ───────────────────────────────────────────────────
     Top-level tabs across the Books view: Pending · Reconcile · Client AR ·
     By Contractor · By Period. Each is a different cross-project lens on
     financial data. Uses the same visual language as project tabs but with
     a slightly heavier baseline since this is the page's primary nav. */
  .books-tabs{
    display:flex;
    gap:0;
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
    padding:0 32px;
  }
  .books-tab{
    padding:14px 22px 14px 0;
    margin-right:22px;
    border:none;
    background:transparent;
    cursor:pointer;
    font-family:var(--font-body);
    font-size:12px;
    font-weight:500;
    letter-spacing:0.12em;
    text-transform:uppercase;
    color:var(--muted);
    border-bottom:2px solid transparent;
    transition:color .15s, border-color .15s;
    white-space:nowrap;
    display:inline-flex;
    align-items:center;
    gap:8px;
    flex-shrink:0;
  }
  .books-tab:hover{color:var(--charcoal2)}
  .books-tab.active{
    color:var(--charcoal);
    border-bottom-color:var(--gold);
  }
  /* Count chip next to a tab label (e.g. Books "Pending 2"). Compact so it
     doesn't visually push the tab off-center inside its flex share. */
  .books-tab-count{
    background:var(--cream3);
    color:var(--charcoal3);
    font-size:9.5px;
    font-weight:600;
    padding:1px 5px;
    border-radius:8px;
    letter-spacing:0.02em;
    line-height:1.4;
  }
  .books-tab.active .books-tab-count,
  .proj-tab.is-active .books-tab-count{
    background:var(--gold-soft);
    color:var(--gold-deep);
  }
  /* Inputs inside project sections — placeholders bumped from --muted2 to
     --muted for slightly better legibility. Muted body text already reads
     well against the white section surface, no override needed. */
  .proj-section .field input::placeholder,
  .proj-section .field textarea::placeholder,
  .proj-section input::placeholder,
  .proj-section textarea::placeholder{color:var(--muted) !important;opacity:1}
  .proj-section-head{display:flex;align-items:center;gap:12px;margin-bottom:18px}
  .proj-section-label{font-size:13px;font-weight:600;letter-spacing:0.005em;color:var(--charcoal2)}
  .proj-section-hint{font-size:11px;color:var(--muted)}
  .proj-section-rule{flex:1;height:1px;background:var(--border)}
  .proj-section > div:nth-child(2){background:transparent !important;border-top:none !important;padding:0 !important}

  /* Run sheet bride row — gold left rule signals "this is the bride" without
     breaking the unified .tbl appearance. Set on the leading <td> via
     box-shadow so it sits inside the cell padding cleanly. */
  .tbl tr.rs-row-bride td:first-child{box-shadow:inset 3px 0 0 var(--gold)}

  /* Run sheet table sits inside the project pane's white .proj-section card,
     so its header gets a cream strip to read as a header band — unlike the
     other .tbl uses, which sit on cream-page surfaces where a white header
     reads better. Scoped to .rs-tbl so we don't disturb the global rule. */
  .rs-tbl thead th{background:var(--cream)}

  /* TABLE */
  /* Horizontal-scroll wrapper for wide data tables. Desktop: no effect, and
     overflow stays visible so in-cell popovers/dropdowns aren't clipped. Phones:
     the table scrolls sideways inside its card instead of crushing 7–8 columns
     into 340px. */
  .tbl-wrap{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  @media(max-width:768px){
    .tbl-wrap>.tbl{min-width:560px}
    .tbl-wrap>.tbl.tbl-narrow{min-width:0}
  }
  .tbl{width:100%;border-collapse:collapse}
  .tbl th{text-align:left;font-size:10px;letter-spacing:0.16em;text-transform:uppercase;color:var(--muted);padding:10px 12px;border-bottom:1px solid var(--border);font-weight:500;background:transparent}
  .tbl td{padding:14px 12px;border-bottom:1px solid var(--cream2);font-size:13px;vertical-align:middle;transition:background .15s var(--ease-smooth)}
  .tbl tr:last-child td{border-bottom:none}
  .tbl tr{transition:background .15s var(--ease-smooth)}
  .tbl tbody tr:hover td{background:var(--cream)}

  /* Numeric column — tabular figures, right-aligned, display-serif feel for
     dollar amounts. Used in Books for billed / paid / outstanding columns. */
  .tbl td.tbl-num,.tbl th.tbl-num{text-align:right;font-variant-numeric:tabular-nums}
  .tbl td.tbl-num-lg{font-family:var(--font-display);font-size:18px;font-weight:300;letter-spacing:0.01em}

  /* Expandable-row pattern.
     A summary row (.tbl-row-expand) can be clicked to reveal a detail row
     (.tbl-row-detail) immediately below it. The detail row uses --cream2
     (one tier deeper than the hover --cream) so the parent/child relation
     is unambiguous even on hover. The chevron rotates when the parent is
     .is-open. Detail rows opt out of the hover gradient so they don't
     compete with the summary row above. */
  .tbl-row-expand{cursor:pointer}
  /* Div-based table rows — per-cell hover gradient matching .tbl tbody tr:hover td */
  .div-tbl-row > div{transition:background .15s var(--ease-smooth)}
  .div-tbl-row:hover > div{background:var(--cream) !important}
  .div-tbl-row.has-status-bg:hover > div{background:inherit !important}
  .tbl-chev{display:inline-block;font-size:11px;color:var(--muted);transition:transform .15s var(--ease-smooth);margin-right:8px;width:10px}
  .tbl-row-expand.is-open .tbl-chev{transform:rotate(90deg);color:var(--gold-dark)}
  .tbl-row-detail > td{background:var(--white);padding:14px 18px;border-bottom:1px solid var(--border-soft)}
  .tbl tbody tr.tbl-row-detail:hover > td{background:var(--white)}

  /* Responsive table cards — opt-in via .tbl.tbl-responsive on the <table>.
     Below 768px each <tr> renders as a stacked card and each <td> uses its
     data-label attribute as an in-cell label. The last cell is marked with
     .action-cell so its buttons get a full-width flex row instead of being
     crammed into a narrow column. Desktop layout is untouched. */
  @media(max-width:768px){
    .tbl-wrap > .tbl.tbl-responsive{min-width:0}
    .tbl.tbl-responsive,
    .tbl.tbl-responsive thead,
    .tbl.tbl-responsive tbody,
    .tbl.tbl-responsive tr,
    .tbl.tbl-responsive td{display:block;width:auto}
    .tbl.tbl-responsive thead{display:none}
    .tbl.tbl-responsive tbody tr{padding:14px 16px;border-bottom:1px solid var(--border-soft)}
    .tbl.tbl-responsive tbody tr:last-child{border-bottom:none}
    /* Detail rows sit flush under the summary card — no extra top padding, no
       duplicated border. The td inside provides its own padding. */
    .tbl.tbl-responsive tbody tr.tbl-row-detail{padding:0;border-bottom:none}
    .tbl.tbl-responsive tbody tr.tbl-row-detail > td{display:block;padding:0 16px 16px 16px}
    .tbl.tbl-responsive tbody tr:hover td,
    .tbl.tbl-responsive tbody tr:hover{background:transparent}
    .tbl.tbl-responsive td{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap:12px;
      padding:6px 0;
      border-bottom:none;
      font-size:13px;
      min-height:24px;
      text-align:right;
    }
    .tbl.tbl-responsive td::before{
      content:attr(data-label);
      font-size:10px;
      letter-spacing:0.14em;
      text-transform:uppercase;
      color:var(--muted);
      font-weight:500;
      flex-shrink:0;
      text-align:left;
    }
    .tbl.tbl-responsive td[data-label=""]::before,
    .tbl.tbl-responsive td:not([data-label])::before{display:none}
    .tbl.tbl-responsive td.tbl-num{justify-content:space-between}
    .tbl.tbl-responsive td.action-cell{
      display:flex;
      flex-wrap:wrap;
      gap:8px;
      padding-top:12px;
      margin-top:8px;
      border-top:1px solid var(--border-soft);
      justify-content:flex-end;
      text-align:left;
    }
    .tbl.tbl-responsive td.action-cell::before{display:none}
    .tbl.tbl-responsive td.action-cell > .btn{margin:0}

    /* Expandable summary row's lead cell — when a table uses tbl-row-expand,
       its first <td> holds the chevron + title composite. On mobile it spans
       the full card width as the header, with no data-label. */
    .tbl.tbl-responsive td.tbl-row-head{
      display:block;
      padding:0 0 10px 0;
      border-bottom:1px solid var(--border-soft);
      margin-bottom:6px;
      text-align:left;
      min-height:0;
    }
    .tbl.tbl-responsive td.tbl-row-head::before{display:none}

    /* Detail row sits flush under its summary card with the desktop cream2
       background so the parent/child relationship reads on mobile too. The
       single <td colspan> becomes a block-level container with no label. */
    .tbl.tbl-responsive tbody tr.tbl-row-detail{
      background:var(--cream2);
      padding:12px 16px;
      margin-top:-1px;
      border-top:1px solid var(--border-soft);
    }
    .tbl.tbl-responsive tbody tr.tbl-row-detail > td{
      display:block;
      padding:0;
      text-align:left;
    }
    .tbl.tbl-responsive tbody tr.tbl-row-detail > td::before{display:none}
  }

  /* BADGES */
  .badge{display:inline-flex;align-items:center;padding:4px 11px;border-radius:20px;font-size:10px;letter-spacing:0.10em;font-weight:600;text-transform:uppercase;line-height:1}
  .badge-gold{background:var(--gold-soft);color:var(--gold-dark);box-shadow:inset 0 0 0 1px rgba(201,169,110,0.18)}
  .badge-green{background:var(--success-soft);color:var(--success);box-shadow:inset 0 0 0 1px rgba(46,125,94,0.18)}
  .badge-gray{background:var(--cream2);color:var(--muted);box-shadow:inset 0 0 0 1px var(--border)}
  .badge-red{background:var(--error-soft);color:var(--error);box-shadow:inset 0 0 0 1px rgba(184,58,44,0.18)}
  .badge-blue{background:rgba(52,100,163,0.10);color:#3464A3;box-shadow:inset 0 0 0 1px rgba(52,100,163,0.18)}

  /* CHIPS — interactive rounded pills. Distinct from .badge (small uppercase
     status indicators). Use .chip for read-only metadata, .chip.chip-toggle
     for selectable, .chip.is-on for selected state. */
  .chip{display:inline-flex;align-items:center;gap:6px;padding:4px 11px;background:var(--white);border:1px solid var(--border);border-radius:999px;font-size:12px;color:var(--charcoal2);line-height:1.4;transition:border-color .15s var(--ease),background .15s var(--ease),color .15s var(--ease)}
  .chip-sm{padding:3px 9px;font-size:11px;gap:5px}
  .chip-lg{padding:6px 14px;font-size:13px;gap:8px}
  .chip-toggle{cursor:pointer;user-select:none;border:none}
  .chip-toggle:hover{border-color:var(--gold-light);background:rgba(201,169,110,0.04)}
  .chip.is-on{background:rgba(201,169,110,0.12);border-color:var(--gold);color:var(--gold-dark)}
  .chip-toggle.is-on:hover{background:rgba(201,169,110,0.18)}
  .chip-gold{background:var(--gold-soft);border-color:var(--gold-light);color:var(--gold-dark)}
  .chip-star::before{content:"★";color:var(--gold);font-size:11px}

  /* AMOUNT DISPLAY — editorial numbers in the display font */
  .amount{font-family:var(--font-display);font-weight:300;color:var(--gold-dark);letter-spacing:0.01em;line-height:1.05}
  .amount-sm{font-size:16px}
  .amount-md{font-size:22px}
  .amount-lg{font-size:32px}
  .amount-xl{font-size:42px}
  .amount-charcoal{color:var(--charcoal)}
  .amount-tabular{font-variant-numeric:tabular-nums}

  /* TBL-MINI — compact key/value table for confirm-modal summaries */
  .tbl-mini{width:100%;border-collapse:collapse;font-size:13px}
  .tbl-mini td{padding:4px 0;color:var(--charcoal2)}
  .tbl-mini td:last-child{text-align:right;font-variant-numeric:tabular-nums}
  .tbl-mini tr.is-total td{padding-top:10px;border-top:1px solid var(--border);color:var(--charcoal);font-weight:500}

  /* KV ROW — key/value pair row for detail views and modals */
  .kv-row{display:flex;align-items:baseline;gap:12px;padding:9px 0;border-bottom:1px solid var(--border-soft)}
  .kv-row:last-child{border-bottom:none}
  .kv-row .kv-label{font-size:11px;letter-spacing:0.12em;text-transform:uppercase;color:var(--muted);min-width:120px;flex-shrink:0}
  .kv-row .kv-value{flex:1;font-size:14px;color:var(--charcoal)}
  .kv-row .kv-value.is-empty{color:var(--muted2)}

  /* SECTION HEAD — labeled divider for cards, modals, panels */
  .section-head{display:flex;align-items:center;gap:12px;margin:18px 0 10px}
  .section-head:first-child{margin-top:0}
  /* Sentence-case section label — the .section-rule hairline beside it still
     carries the structural divider, so we don't need the uppercase tracking
     to signal "this is a section header" anymore. Calmer on dense pages. */
  .section-label{font-size:13px;font-weight:600;letter-spacing:0.005em;color:var(--charcoal2)}
  .section-hint{font-size:11px;color:var(--muted);font-weight:300}
  .section-rule{flex:1;height:1px;background:var(--border)}

  /* MODAL */
  .modal-overlay{position:fixed;inset:0;background:rgba(35,32,28,0.55);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:none;align-items:center;justify-content:center;z-index:100;padding:20px;animation:fadeIn .25s var(--ease-smooth) both}
  .modal-overlay.is-open{display:flex}
  .modal{background:var(--white);border-radius:var(--radius-xl);padding:34px;width:100%;max-width:520px;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg);position:relative;animation:modalIn .35s var(--ease) both;border:1px solid var(--border-soft)}
  .modal::before{content:"";position:absolute;top:0;left:24px;right:24px;height:1px;background:linear-gradient(90deg,transparent,var(--gold),transparent);opacity:0.6}
  @keyframes modalIn{from{opacity:0;transform:translateY(12px) scale(0.98)}to{opacity:1;transform:none}}
  .modal::-webkit-scrollbar{width:6px}
  .modal::-webkit-scrollbar-thumb{background:rgba(44,40,37,0.12);border-radius:3px}
  .modal-title{font-family:var(--font-display);font-size:26px;font-weight:400;margin-bottom:22px;letter-spacing:0.015em;color:var(--charcoal);line-height:1.1}
  .modal-title-row{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
  .modal-title-row > span:first-child{flex:1;min-width:0}
  .modal-close-x{background:none;border:none;font-size:22px;color:var(--muted);cursor:pointer;line-height:1;padding:4px 8px;margin:-4px -8px 0 0}
  .modal-sub{font-size:13px;color:var(--muted);margin:-6px 0 18px;line-height:1.55}
  .modal-prose{font-size:14px;line-height:1.65;color:var(--charcoal2);white-space:pre-wrap}
  .modal.modal-sm{max-width:420px}
  .modal.modal-md{max-width:480px}
  .modal.modal-lg{max-width:560px}
  .modal.modal-xl{max-width:640px}
  .modal-footer{display:flex;gap:10px;justify-content:flex-end;margin-top:26px;padding-top:22px;border-top:1px solid var(--border)}
  .two-col{display:grid;grid-template-columns:1fr 1fr;gap:14px}

  /* INVOICE ITEMS */
  .invoice-line{display:flex;align-items:center;gap:10px;padding:12px 14px;background:var(--cream);border-radius:var(--radius);margin-bottom:8px;border:1px solid var(--border-soft);transition:border-color .2s,background .2s}
  .invoice-line:hover{border-color:var(--border);background:var(--cream)}
  .invoice-line-name{flex:1;font-size:14px}
  .invoice-line-price{font-family:var(--font-display);font-size:18px;font-weight:400;color:var(--gold-dark);min-width:80px;text-align:right;letter-spacing:0.01em}
  .invoice-total{display:flex;justify-content:space-between;align-items:center;padding:18px 14px 4px;border-top:1px solid var(--border);margin-top:12px}
  .invoice-total-label{font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);font-weight:500}
  .invoice-total-val{font-family:var(--font-display);font-size:32px;font-weight:300;color:var(--charcoal);letter-spacing:0.01em}
  /* Invoice-builder line-item grid. Five columns (service / qty stepper / unit
     price / you-get / remove). On phones the fixed columns are tightened so the
     right-hand columns don't clip off-screen and service names don't wrap to
     four lines. */
  .inv-line{display:grid;grid-template-columns:1fr 88px 96px 92px 24px;gap:0}
  @media(max-width:768px){
    /* Mirror the estimate row's mobile restack: description + delete on row 1,
       qty / unit price / line total on row 2. Header row hides on mobile. */
    .inv-line{
      grid-template-columns:1fr 1fr 1fr auto;
      grid-template-areas:
        "name name name actions"
        "qty  price total total";
      row-gap:6px;
      padding:8px 4px !important;
    }
    .inv-line > :nth-child(1){grid-area:name;padding:2px 10px 0 !important;font-size:13.5px !important;font-weight:500}
    .inv-line > :nth-child(2){grid-area:qty;padding:0 0 0 10px !important;justify-content:flex-start !important}
    .inv-line > :nth-child(3){grid-area:price;padding:0 !important;justify-content:center !important}
    .inv-line > :nth-child(4){grid-area:total;padding:0 10px 0 0 !important;justify-content:flex-end !important;font-size:14px !important}
    .inv-line > :nth-child(5){grid-area:actions;padding:2px 10px 0 0 !important;justify-content:flex-end !important}
    .inv-line-header{display:none !important}
  }

  /* EMPTY STATE */
  .empty{text-align:center;padding:56px 24px;color:var(--muted)}
  .empty-icon{font-size:40px;margin-bottom:14px;opacity:0.3}
  .empty-title{font-family:var(--font-display);font-size:22px;font-weight:400;color:var(--charcoal2);margin-bottom:8px;letter-spacing:0.01em}
  .empty p{font-size:13px;max-width:340px;margin:0 auto;line-height:1.6}

  /* TIMELINE / STATUS */
  .status-bar{display:flex;align-items:center;gap:6px}
  .status-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;box-shadow:0 0 0 3px rgba(0,0,0,0.04)}
  .dot-green{background:var(--success);box-shadow:0 0 0 3px var(--success-soft)}
  .dot-gold{background:var(--gold);box-shadow:0 0 0 3px var(--gold-soft)}
  .dot-gray{background:var(--muted2)}
  .dot-red{background:var(--error);box-shadow:0 0 0 3px var(--error-soft)}

  /* CONTRACTOR INVOICE PAGE */
  .service-picker{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;margin-bottom:22px}
  .service-tile{border:1px solid var(--border);border-radius:var(--radius);padding:16px;cursor:pointer;transition:transform .2s var(--ease),border-color .2s var(--ease),background .2s var(--ease),box-shadow .2s var(--ease);background:var(--white);position:relative}
  .service-tile:hover{border-color:var(--gold);background:rgba(201,169,110,0.04);transform:translateY(-1px);box-shadow:var(--shadow)}
  .service-tile.selected{border-color:var(--gold);background:rgba(201,169,110,0.09);box-shadow:0 0 0 1px var(--gold),var(--shadow)}
  .service-tile-name{font-size:13px;font-weight:500;margin-bottom:6px;color:var(--charcoal)}
  .service-tile-price{font-family:var(--font-display);font-size:20px;font-weight:300;color:var(--gold-dark);letter-spacing:0.01em}

  /* LOADER */
  .loader{display:inline-block;width:18px;height:18px;border:2px solid rgba(255,255,255,0.3);border-top-color:var(--white);border-radius:50%;animation:spin .7s linear infinite}
  @keyframes spin{to{transform:rotate(360deg)}}

  /* NOTICE */
  .notice{padding:14px 18px;border-radius:var(--radius);font-size:13px;margin-bottom:18px;line-height:1.55}
  .notice-warn{background:rgba(201,169,110,0.10);color:var(--gold-deep);border-left:3px solid var(--gold)}
  .notice-info{background:rgba(52,100,163,0.07);color:#264E80;border-left:3px solid #3464A3}
  .notice-success{background:var(--success-soft);color:var(--success);border-left:3px solid var(--success)}
  .notice-err{background:rgba(184,58,44,0.06);color:var(--error);border-left:3px solid var(--error)}

  input[type=number]{-moz-appearance:textfield}
  input[type=number]::-webkit-outer-spin-button,input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none}

  /* TOAST */
  #toast{font-family:var(--font-body)!important;font-weight:500;letter-spacing:0.02em;line-height:1.4;animation:toastIn .35s var(--ease) both;border:1px solid rgba(255,255,255,0.08)}
  @keyframes toastIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

  /* DASHBOARD upcoming-events table — venue stack only shows on mobile;
     desktop keeps the four-column layout (client | date | venue | status). */
  .dash-upcoming-venue-stack{display:none}
  .dash-upcoming-date{white-space:nowrap}
  .dash-upcoming-venue{max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  @media(max-width:768px){
    /* Drop the horizontal scroller for this table — we'd rather compress
       cleanly than make people swipe to read a venue. */
    .dash-upcoming-wrap{overflow-x:visible}
    .dash-upcoming-wrap > .tbl{min-width:0}
    /* Hide standalone venue + status columns; venue moves under client name. */
    .dash-upcoming th:nth-child(3),
    .dash-upcoming td.dash-upcoming-venue,
    .dash-upcoming th:nth-child(4),
    .dash-upcoming td.dash-upcoming-status{display:none}
    /* Tighten cell padding and bring the client column off the left edge. */
    .dash-upcoming th,.dash-upcoming td{padding:11px 10px}
    .dash-upcoming th:first-child,.dash-upcoming td:first-child{padding-left:18px}
    .dash-upcoming th:last-child,.dash-upcoming td:last-child{padding-right:18px}
    .dash-upcoming-venue-stack{
      display:block;font-size:11px;color:var(--muted);
      margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
      max-width:100%;
    }
    .dash-upcoming-client{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}
    /* Keep the date compact and right-aligned so the wider client column
       breathes. */
    .dash-upcoming-date{text-align:right;color:var(--charcoal3);font-size:12px}
  }

  /* ESTIMATE LINE ITEMS — used by both Services and Lodging tables. Desktop
     is a 5-column grid (name | qty | unit price | total | actions); phone
     restacks to: name + delete on row 1; qty/price/total on row 2. */
  .est-row{
    display:grid;
    grid-template-columns:1fr 88px 96px 72px 24px;
    align-items:stretch;background:var(--white);
  }
  .est-row.est-row-days{grid-template-columns:1fr 84px 92px 72px auto}
  .est-row.est-row-divided{border-top:1px solid var(--border-soft)}
  .est-header{
    padding:7px 12px;font-size:10px;letter-spacing:0.1em;
    text-transform:uppercase;color:var(--muted);font-weight:500;
    border-bottom:1px solid var(--border-soft);
  }
  .est-cell{padding:8px 12px;display:flex;align-items:center;font-size:13px;color:var(--charcoal)}
  .est-cell-qty{padding:8px 4px;justify-content:center;gap:0}
  .est-cell-price{padding:8px 4px;justify-content:center;gap:3px}
  .est-cell-total{
    padding:8px 12px;justify-content:flex-end;text-align:right;
    font-family:var(--font-display);color:var(--gold-dark);
    font-size:15px;font-weight:500;
  }
  .est-cell-actions{padding:8px 8px;justify-content:flex-end;gap:6px}
  /* qty stepper buttons + read-out */
  .est-qty-btn{
    width:22px;height:26px;border:1px solid var(--border-soft);
    background:var(--cream2);color:var(--charcoal2);
    font-size:14px;line-height:1;cursor:pointer;
    display:flex;align-items:center;justify-content:center;padding:0;
    transition:background .12s;
  }
  .est-qty-btn-l{border-right:none;border-radius:var(--radius-sm) 0 0 var(--radius-sm)}
  .est-qty-btn-r{border-left:none;border-radius:0 var(--radius-sm) var(--radius-sm) 0}
  .est-qty-btn:hover{background:var(--cream3)}
  .est-qty-val{
    width:28px;height:26px;border:1px solid var(--border-soft);
    background:var(--white);font-size:13px;font-family:var(--font-body);
    text-align:center;color:var(--charcoal);display:flex;
    align-items:center;justify-content:center;font-weight:500;
  }
  /* unit price (dbl-click to edit) */
  .est-price-sign{font-size:11px;color:var(--muted)}
  .est-price-val{font-size:13px;color:var(--charcoal3);cursor:text;padding:2px 4px;border-radius:3px}
  .est-price-input{
    display:none;width:56px;padding:2px 4px;border:none;
    border-bottom:1.5px solid var(--gold);border-radius:0;
    font-size:13px;font-family:var(--font-body);background:transparent;
    text-align:right;color:var(--charcoal);outline:none;
  }
  /* row actions */
  .est-move-pill{
    display:inline-flex;align-items:center;gap:2px;
    padding:2px 8px;border:1px solid var(--border);background:var(--white);
    border-radius:14px;font-size:10px;color:var(--charcoal3);cursor:pointer;
    white-space:nowrap;transition:all .12s;
  }
  .est-move-pill:hover{border-color:var(--gold);color:var(--gold-dark)}
  .est-remove-btn{
    background:transparent;border:none;cursor:pointer;
    color:var(--muted);font-size:16px;line-height:1;padding:0;
    transition:color .15s;
  }
  .est-remove-btn:hover{color:var(--error)}
  .est-lodging-name{cursor:text;padding:2px 4px;border-radius:3px;color:var(--charcoal)}
  @media(max-width:768px){
    /* Phone: description + delete on row 1, controls (qty/price/total) on row 2. */
    .est-row,
    .est-row.est-row-days{
      grid-template-columns:1fr 1fr 1fr auto;
      grid-template-areas:
        "name name name actions"
        "qty  price total total";
      row-gap:6px;padding:8px 4px;
    }
    .est-cell-name   {grid-area:name;padding:2px 10px 0;font-size:13.5px;font-weight:500}
    .est-cell-qty    {grid-area:qty;padding:0 0 0 10px;justify-content:flex-start}
    .est-cell-price  {grid-area:price;padding:0;justify-content:center}
    .est-cell-total  {grid-area:total;padding:0 10px 0 0;justify-content:flex-end;font-size:14px}
    .est-cell-actions{grid-area:actions;padding:2px 10px 0 0;justify-content:flex-end}
    .est-header{display:none}
  }

  /* RECONCILIATION DETAIL TABLE — used inside the project Payouts panel and
     inside each event card in Books > Reconcile. Desktop is a 5-column table
     (service | est | invoiced | billed by | status). Mobile collapses each
     row into a small card so "Not yet billed" and contributor lists don't
     wrap into 3-character columns. */
  .recon-tbl{
    background:var(--white);
    border:1px solid var(--border);border-radius:var(--radius);
    overflow:hidden;margin-bottom:16px;
  }
  .recon-tbl-panel{border:1px solid var(--border)}
  .recon-tbl-books{border:none;margin-bottom:0;border-radius:0}
  .recon-tbl-head,
  .recon-tbl-row{
    display:grid;
    grid-template-columns:1.6fr 0.7fr 0.9fr 1.4fr 0.9fr;
    gap:0;align-items:stretch;
  }
  .recon-tbl-head{
    padding:8px 12px;font-size:10px;letter-spacing:0.1em;
    text-transform:uppercase;color:var(--muted);font-weight:500;
    border-bottom:1px solid var(--border);
  }
  .recon-tbl-panel .recon-tbl-head{
    background:rgba(201,169,110,0.10);
    border-bottom:1px solid var(--gold-light);
  }
  .recon-tbl-row{background:var(--white)}
  .recon-tbl-row + .recon-tbl-row{border-top:1px solid var(--border-soft)}
  .recon-tbl-row-over{background:rgba(184,58,44,0.05)}
  .recon-tbl-row-under{background:rgba(201,169,110,0.05)}
  .recon-cell{padding:10px 12px;font-size:13px}
  .recon-cell-name{font-size:13px}
  .recon-cell-est,
  .recon-cell-inv{
    text-align:center;font-family:var(--font-display);font-size:15px;
    color:var(--charcoal2);
  }
  .recon-cell-inv.is-muted{color:var(--muted)}
  .recon-cell-inv.is-matches{color:var(--success)}
  .recon-cell-inv.is-over{color:var(--error)}
  .recon-cell-inv.is-under{color:var(--gold-dark)}
  .recon-cell-billed{font-size:11px;color:var(--charcoal3)}
  .recon-cell-status{text-align:center}
  /* Status chips with intent colors */
  .recon-status{font-size:11px;font-weight:500;white-space:nowrap}
  .recon-status-unbilled{color:var(--muted);font-style:italic}
  .recon-status-matches{color:var(--success)}
  .recon-status-over{color:var(--error)}
  .recon-status-under{color:var(--gold-dark);font-size:11px;letter-spacing:0.04em;font-weight:500}
  .recon-self-badge{
    font-size:9px;font-weight:600;letter-spacing:0.06em;text-transform:uppercase;
    color:var(--gold-dark);background:rgba(201,169,110,0.15);
    padding:1px 5px;border-radius:8px;margin-left:2px;
  }
  @media(max-width:768px){
    /* Hide the column header strip on mobile — each row carries its own
       data-label-prefixed cells in card form. */
    .recon-tbl-head{display:none}
    .recon-tbl-row{
      grid-template-columns:1fr auto;
      grid-template-areas:
        "name status"
        "qtys qtys"
        "billed billed";
      row-gap:6px;
      padding:12px;
    }
    .recon-cell{padding:0}
    .recon-cell-name{grid-area:name;font-weight:500;font-size:13.5px}
    .recon-cell-status{grid-area:status;text-align:right;justify-self:end}
    /* Pack est / invoiced side-by-side with their tiny field labels */
    .recon-cell-est,
    .recon-cell-inv{
      grid-area:qtys;text-align:left;font-size:13px;
      display:flex;align-items:baseline;gap:4px;font-family:var(--font-body);
    }
    .recon-cell-est{
      grid-column:1;grid-row:2;
    }
    .recon-cell-inv{
      grid-column:2;grid-row:2;justify-self:end;
    }
    .recon-cell-est::before,
    .recon-cell-inv::before,
    .recon-cell-billed::before{
      content:attr(data-label) ":";
      font-size:10px;letter-spacing:0.08em;text-transform:uppercase;
      color:var(--muted);font-weight:500;
      font-family:var(--font-body);
    }
    .recon-cell-billed{
      grid-area:billed;font-size:12px;
      padding-top:4px;border-top:1px dashed var(--border-soft);
      display:flex;flex-direction:column;gap:2px;
    }
    .recon-cell-billed::before{margin-top:4px}
  }

  /* RECONCILIATION CARD — one event card in Books > Reconcile (and also the
     Payouts cross-event summary). Desktop keeps the single-row layout; mobile
     stacks: title row, meta chips row, full-width Open button. */
  .recon-card{
    background:var(--white);border:1px solid var(--border);
    border-radius:var(--radius);margin-bottom:8px;overflow:hidden;
  }
  .recon-card-head{
    display:grid;
    grid-template-columns:auto 1fr auto auto;
    grid-template-areas:"caret title meta open";
    align-items:center;gap:12px;padding:12px 14px;cursor:pointer;
  }
  .recon-card-caret{
    grid-area:caret;font-size:14px;color:var(--muted);
    transition:transform .15s;line-height:1;
  }
  .recon-card-caret.is-open{transform:rotate(90deg)}
  .recon-card-title{grid-area:title;min-width:0}
  .recon-card-name{
    font-size:14px;font-weight:500;color:var(--charcoal);
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  .recon-card-sub{font-size:11px;color:var(--muted);margin-top:2px}
  .recon-card-meta{
    grid-area:meta;display:flex;align-items:center;gap:14px;flex-shrink:0;
  }
  .recon-card-stats{font-size:11px;color:var(--charcoal3)}
  .recon-card-open{grid-area:open}
  @media(max-width:768px){
    .recon-card-head{
      grid-template-columns:auto 1fr;
      grid-template-areas:
        "caret title"
        "meta meta"
        "open open";
      row-gap:8px;padding:12px 14px;
    }
    .recon-card-meta{flex-wrap:wrap;gap:10px}
    .recon-card-stats{font-size:11.5px}
    .recon-card-open{justify-self:start;width:auto}
  }

  /* STRIPE LINK CARD — Retainer / balance invoice URL display in Client
     Invoicing. URL on row 1 (full-width, scrolls if long); Copy Link + Open
     share row 2 as equal halves so neither overhangs into a third row. */
  .stripe-link-card{
    display:flex;flex-direction:column;gap:8px;
    padding:8px 10px;background:var(--white);
    border:1px solid var(--border);
    border-radius:calc(var(--radius) - 2px);
  }
  .stripe-link-url{
    width:100%;border:none;background:transparent;
    font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;
    font-size:10px;color:var(--charcoal2);outline:none;padding:2px 0;
    text-overflow:ellipsis;
  }
  .stripe-link-actions{display:flex;gap:6px}
  .stripe-link-actions > .btn{
    flex:1 1 0;min-width:0;padding:5px 10px;font-size:11px;
    letter-spacing:0.06em;display:inline-flex;align-items:center;
    justify-content:center;gap:6px;text-decoration:none;white-space:nowrap;
  }

  /* PANEL ACTION ROW — shared layout for the footer button strip on the
     Estimate / Contract / Client Invoicing panels. Buttons share the row,
     wrap when needed, never let their label text wrap inside a single button. */
  .panel-action-row{
    display:flex;gap:8px;flex-wrap:wrap;align-items:center;
  }
  .panel-action-row > .btn{
    flex:1 1 130px;min-width:0;
    padding:8px 14px;font-size:11.5px;letter-spacing:0.08em;
    white-space:nowrap;text-overflow:ellipsis;overflow:hidden;
    display:inline-flex;align-items:center;justify-content:center;gap:7px;
  }
  /* Inline SVG icon paired with a button label. iOS fonts don't reliably
     ship glyphs like ⤴ / ⧉ / ↻, so we use SVG instead of unicode for any
     button that needs a leading icon. */
  .btn-icon{width:13px;height:13px;flex-shrink:0}
  @media(max-width:768px){
    .panel-action-row{gap:6px}
    .panel-action-row > .btn{flex:1 1 calc(50% - 4px);font-size:11px;padding:8px 10px;letter-spacing:0.04em}
    .btn-icon{width:12px;height:12px}
  }

  /* CONTRACT ACTION GROUP — primary actions (View / Copy Link) share a row
     via .contract-action-row (same shape as .panel-action-row); the
     destructive "Cancel Contract" sits below with extra spacing so it reads
     as a quieter, distinct option rather than a peer-with-equal-weight. */
  .contract-action-group{margin-top:12px}
  .contract-action-row{
    display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:14px;
  }
  .contract-action-row > .btn{
    flex:1 1 130px;min-width:0;
    padding:8px 14px;font-size:11.5px;letter-spacing:0.08em;
    white-space:nowrap;text-overflow:ellipsis;overflow:hidden;
  }
  .contract-cancel-btn{
    padding:7px 16px;font-size:11.5px;
    color:var(--error);border-color:rgba(184,58,44,0.22);
    background:transparent;
  }
  .contract-cancel-btn:hover{
    background:rgba(184,58,44,0.05);
    border-color:rgba(184,58,44,0.5);
  }
  @media(max-width:768px){
    .contract-action-row{gap:6px}
    .contract-action-row > .btn{flex:1 1 calc(50% - 4px);font-size:11px;padding:8px 10px}
  }

  /* PROJECT DETAIL TOPBAR — two-row layout:
       Row 1 (proj-crumb-row): hamburger · ← Events ............... Delete
       Row 2 (proj-title-block): big title with status badge + subtitle
     Keeps hamburger and the navigation chrome on the same baseline, so the
     hamburger no longer floats high above the title. */
  .proj-detail-topbar{
    flex-direction:column;align-items:stretch;gap:8px;
    padding-top:calc(18px + env(safe-area-inset-top));
    padding-bottom:14px;
    position:static;border-bottom:none;box-shadow:none;
  }
  .proj-crumb-row{display:flex;align-items:center;gap:12px}
  .proj-crumb-back{
    background:transparent;border:none;cursor:pointer;
    padding:4px 0;font-family:var(--font-body);font-size:12px;
    letter-spacing:0.14em;text-transform:uppercase;font-weight:500;
    color:var(--muted);display:inline-flex;align-items:center;gap:6px;
    transition:color .15s;
  }
  .proj-crumb-back:hover{color:var(--charcoal)}
  .proj-crumb-delete{
    background:transparent;border:none;cursor:pointer;
    padding:4px 0;margin-left:auto;font-family:var(--font-body);font-size:12px;
    letter-spacing:0.14em;text-transform:uppercase;font-weight:500;
    color:var(--muted);transition:color .15s;
  }
  .proj-crumb-delete:hover{color:var(--error)}
  .proj-title-block{
    min-width:0;
    /* Animate height/opacity for the mobile scroll-collapse below. Desktop
       never triggers the collapsed state, so the transition is invisible. */
    max-height:300px;opacity:1;
    transition:
      max-height .25s var(--ease-smooth),
      opacity .15s var(--ease-smooth),
      margin .25s var(--ease-smooth);
    overflow:hidden;
  }
  @media(max-width:768px){
    /* When the user scrolls past ~56px the JS adds .is-compact, collapsing
       the big title row down to nothing. The crumb row + tabs stay pinned. */
    .proj-detail-topbar.is-compact{padding-top:calc(8px + env(safe-area-inset-top));padding-bottom:6px}
    .proj-detail-topbar.is-compact .proj-title-block{
      max-height:0;opacity:0;margin:0;
    }
  }

  /* PROJECT DETAIL — tab strip. Tabs share the available width equally on
     desktop (Overview · Team · Schedule · Money) so they don't bunch to the
     left of the page. Mobile keeps the same equal-share treatment but hides
     the hint subtitles ("4 confirmed", "15 blocks") so labels stay legible. */
  .proj-tabs{
    padding:0 32px;display:flex;gap:0;
    border-top:1px solid var(--border-soft);
  }
  .proj-tab{
    flex:1 1 0;min-width:0;
    background:transparent;border:none;cursor:pointer;
    padding:14px 8px;
    font-family:var(--font-body);font-size:12px;letter-spacing:0.12em;
    text-transform:uppercase;font-weight:500;color:var(--muted);
    border-bottom:2px solid transparent;
    transition:color .15s,border-color .15s;
    display:inline-flex;align-items:center;justify-content:center;gap:10px;
    white-space:nowrap;
  }
  .proj-tab.is-active{color:var(--charcoal);border-bottom-color:var(--gold)}
  .proj-tab-hint{
    font-size:10px;color:var(--muted);letter-spacing:0.04em;
    text-transform:none;font-weight:400;
  }
  /* Small gold attention dot rendered inline with a tab label when there are
     items waiting (e.g. Books "Pending"). Quieter and less width-disrupting
     than a numbered chip — the actual count surfaces inside the tab itself. */
  .proj-tab-dot{
    display:inline-block;width:6px;height:6px;border-radius:50%;
    background:var(--gold-dark);margin-left:6px;vertical-align:1px;
  }
  .proj-tab.is-active .proj-tab-dot{background:var(--gold-deep)}
  @media(max-width:768px){
    .proj-tabs{padding:0 8px}
    .proj-tab{padding:12px 4px;font-size:11px;letter-spacing:0.08em;gap:6px}
    .proj-tab-hint{display:none}
  }

  /* ACTION MENU — a "+ New ▾" split-button used in the events topbar.
     Generic wrapper so other pages can adopt the same pattern. */
  .action-menu-wrap{position:relative;display:inline-block}
  .action-menu-trigger{display:inline-flex;align-items:center;gap:6px}
  .action-menu-caret{font-size:10px;line-height:1;opacity:0.8;transition:transform .15s var(--ease-smooth)}
  .action-menu-wrap.is-open .action-menu-caret{transform:rotate(180deg)}
  .action-menu-pop{
    display:none;position:absolute;top:calc(100% + 8px);right:0;z-index:60;
    background:var(--white);border:1px solid var(--border);
    border-radius:var(--radius);box-shadow:0 6px 24px rgba(44,40,37,0.14);
    padding:6px;min-width:260px;
  }
  .action-menu-wrap.is-open .action-menu-pop{display:block}
  .action-menu-item{
    display:flex;align-items:flex-start;gap:12px;width:100%;
    background:none;border:none;cursor:pointer;text-align:left;
    padding:10px 12px;border-radius:6px;font-family:var(--font-body);
    color:var(--charcoal);transition:background .12s;
  }
  .action-menu-item:hover{background:var(--cream)}
  .action-menu-item > span{display:flex;flex-direction:column;gap:2px;font-size:13px}
  .action-menu-item .action-menu-sub{font-size:11px;color:var(--muted);font-weight:400}
  .action-menu-icon{
    width:22px;flex-shrink:0;font-size:16px;line-height:1.1;
    color:var(--charcoal2);text-align:center;
  }

  /* TEAM BID CARD — one row per contractor response in the Team panel.
     Desktop: single horizontal row (num | avatar | name+ts | status | actions).
     Mobile: stacks to keep the status badge from overlapping the timestamp
     when the row gets squeezed. */
  .team-bid{
    display:grid;
    grid-template-columns:auto auto 1fr auto auto;
    grid-template-areas:"num avatar meta status actions";
    align-items:center;
    gap:10px;
    padding:8px 12px;
    margin-bottom:6px;
    background:var(--cream2);
    border:1px solid var(--border);
    border-radius:var(--radius);
  }
  .team-bid.is-confirmed{background:var(--white);border-color:rgba(46,125,94,0.35)}
  .team-bid.is-waitlist{border-color:rgba(201,169,110,0.3)}
  .team-bid-num{grid-area:num;font-size:11px;color:var(--muted);font-weight:600;min-width:14px}
  .team-bid-avatar{grid-area:avatar;width:28px;height:28px;border-radius:50%;background:var(--gold-light);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;color:var(--gold-dark);flex-shrink:0}
  .team-bid-meta{grid-area:meta;min-width:0}
  .team-bid-name{font-size:12.5px;font-weight:500;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
  .team-bid-ts{font-size:11px;color:var(--muted);margin-top:2px}
  .team-bid-status{grid-area:status;justify-self:end}
  .team-bid-actions{grid-area:actions;display:flex;gap:4px;flex-shrink:0}
  .team-bid-btn{padding:4px 10px;font-size:10px}
  @media(max-width:600px){
    .team-bid{
      grid-template-columns:auto auto 1fr;
      grid-template-areas:
        "num avatar meta"
        "status status status"
        "actions actions actions";
      row-gap:8px;
      padding:10px 12px;
    }
    .team-bid-status{justify-self:start}
    .team-bid-actions{flex-wrap:wrap}
    .team-bid-actions .team-bid-btn{flex:1 1 auto;min-height:32px;padding:6px 10px;font-size:11px}
  }

  /* MOBILE */
  .hamburger{display:none;background:none;border:none;cursor:pointer;padding:6px;color:var(--charcoal);flex-shrink:0;border-radius:var(--radius-sm);transition:background .15s;align-items:center;justify-content:center;min-width:44px;min-height:44px}
  .hamburger:hover{background:var(--cream2)}
  /* Compact back button for drill-in pages (e.g. contractor event detail). */
  .btn-back{display:inline-flex;align-items:center;justify-content:center;min-width:40px;min-height:40px;padding:6px;background:var(--white);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--charcoal);font-size:18px;line-height:1;cursor:pointer;flex-shrink:0;transition:border-color .15s,background .15s}
  .btn-back:hover{border-color:var(--charcoal);background:var(--cream)}
  .hamburger svg{width:22px;height:22px;display:block}
  /* Bleed past bottom:0 by the safe-area inset so the dim covers the home-
     indicator strip too — otherwise the strip reads as a separate flat band
     under the menu instead of part of the dimmed backdrop. */
  .sidebar-overlay{display:none;position:fixed;inset:0;bottom:calc(0px - env(safe-area-inset-bottom));background:rgba(35,32,28,0.55);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);z-index:40;animation:fadeIn .25s var(--ease-smooth) both}
  .sidebar-overlay.open{display:block}
  @media(max-width:768px){
    /* Bleed past bottom:0 by the safe-area inset so the panel's footer fills the
       home-indicator strip on the left, matching the overlay on the right. The
       footer's own padding-bottom keeps its content clear of the indicator. */
    .sidebar{position:fixed;top:0;left:0;bottom:calc(0px - env(safe-area-inset-bottom));z-index:50;transform:translateX(-100%);transition:transform .3s var(--ease);width:260px;min-width:0;box-shadow:none;padding-top:env(safe-area-inset-top)}
    .sidebar.open{transform:translateX(0);box-shadow:var(--shadow-lg)}
    .sidebar-footer{padding-bottom:calc(18px + env(safe-area-inset-bottom))}
    .hamburger{display:flex;align-items:center;justify-content:center}
    /* Clear the iPhone status bar / clock (status bar style is translucent,
       so the web view draws underneath it). Wrap so action buttons (List /
       Calendar / Subscribe) drop to a second row instead of running off-screen. */
    .topbar{padding:calc(14px + env(safe-area-inset-top)) 16px 14px;gap:10px;flex-wrap:wrap;row-gap:10px}
    /* Let the title block flex and shrink so a long subtitle can't inflate its
       width and shove the action button (or the title itself) onto a second
       row under the hamburger. The title ellipsizes; secondary controls wrap. */
    /* Title flexes to fill, but keeps a floor so a crowded topbar (e.g. the
       calendar's List/Calendar toggle + Subscribe) overflows and wraps the
       LAST action down — keeping the toggle on row 1 with the title.
       flex-basis:0 + min-width:0 ensures the title block doesn't claim its
       max-content width (which long subtitles can inflate to), so the title
       sits next to the hamburger instead of wrapping below. */
    .topbar > :has(> .topbar-title){flex:1 1 0;min-width:0}
    .topbar-title{font-size:22px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .topbar-sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    /* When a topbar's single trailing action wraps to its own row (e.g. Invoices'
       "+ Submit Invoice"), stretch it across the row so it reads as a clear
       primary action instead of a floating right-aligned chip on an empty row. */
    .topbar > .btn:last-child:nth-child(3){flex:1 1 100%;margin-left:0}
    /* Promote the grouped action buttons to direct topbar items so they wrap
       individually instead of dropping as one block — the view toggle stays
       up top and only Subscribe (the last item) drops to the next row. */
    .topbar-actions{display:contents}
    /* Auto-fit to the row width on phones: nowrap + flex:1 makes every pill
       claim an equal share of the available space, so 3 pills look like a
       3-segment toggle and 5 pills look like a 5-segment toggle — never any
       awkward gap at the right edge, never a wrap. The 44px tap area comes
       from min-height in the base .filter-pill rule. */
    .filter-pills{gap:5px;margin-bottom:16px;flex-wrap:nowrap;flex:1 1 100%}
    .filter-pill{flex:1 1 0;min-width:0;padding:7px 6px;font-size:11px;letter-spacing:0.03em;white-space:nowrap}
    /* Books / Invoices event filter — full-width row on mobile so the dropdown
       can't push off-screen with long event names. */
    .inv-event-filter{flex:1 1 100% !important;margin-left:0 !important}
    .inv-event-filter > select{flex:1 1 auto;min-width:0 !important;width:100%}
    .page{padding:18px 16px 28px}
    .stats-row{grid-template-columns:1fr 1fr;gap:12px}
    .stat-card{padding:18px}
    .stat-value{font-size:28px}
    .two-col{grid-template-columns:1fr}
    /* Center vertically (inherits align-items:center from the desktop rule).
       Respect the iOS notch / status bar and home-indicator strip via env()
       insets so tall modals don't tuck content behind them. max() keeps
       Android phones with no inset from going edge-to-edge. */
    .modal-overlay{
      padding:max(14px, env(safe-area-inset-top)) 14px max(14px, env(safe-area-inset-bottom))
    }
    .modal{padding:24px 20px;max-height:calc(92dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom))}
    .modal-title{font-size:22px}
    /* Full-width, comfortably tappable footer buttons; wrap instead of
       overflowing when a modal has 3–4 actions. */
    .modal-footer{flex-wrap:wrap;gap:8px;justify-content:stretch}
    .modal-footer>.btn{flex:1 1 132px}
    .card{padding:20px 18px}
    .proj-section{padding:18px 16px}
    .tbl th,.tbl td{padding:9px 6px;font-size:12px}
    .auth-card{padding:36px 26px 30px}

    /* iOS Safari zooms the whole page in when a focused control's font is
       under 16px, and never zooms back — which is why logging in (14px login
       fields) left the next screen "stuck zoomed". Force standard form
       controls to 16px on small screens. Scoped to real form fields so the
       tiny inline price/qty editors in the invoice builder keep their layout. */
    .field input,.field select,.field textarea,
    .u-input,
    select{font-size:16px}

    /* Calendar: phones can't fit 7 readable columns of text events, and the
       90px cells made the month absurdly tall. Shrink the cells and reduce
       each event to its colored glyph marker (◆ / ◈ / ◇) — the label text is
       hidden; tap a day or the marker to see details. !important overrides the
       inline cell/event styles set in calRender(). */
    .cal-cell{min-height:48px !important;padding:4px 3px !important}
    .cal-event{display:inline-block !important;background:transparent !important;
      border-left:none !important;border-radius:0 !important;
      padding:0 1px !important;margin:0 1px 0 0 !important;
      font-size:0 !important;line-height:1 !important;vertical-align:top;max-width:none}
    .cal-event > span{font-size:13px !important;margin:0 !important}
  }

  /* ─── SUBSCRIPTION UI ─────────────────────────────────────────────────── */
  .sub-banner{margin:0 0 18px;padding:13px 18px;border-radius:var(--radius);font-size:13px;line-height:1.55;display:flex;align-items:center;gap:14px;flex-wrap:wrap}
  .sub-banner-trial{background:var(--gold-soft);color:var(--gold-deep);border:1px solid rgba(201,169,110,0.3)}
  .sub-banner-warn{background:rgba(201,169,110,0.18);color:var(--gold-deep);border:1px solid var(--gold)}
  .sub-banner-err{background:var(--error-soft);color:var(--error);border:1px solid rgba(184,58,44,0.25)}
  .sub-banner .sub-banner-text{flex:1;min-width:200px}
  .sub-banner strong{font-weight:600}
  .sub-banner button{flex-shrink:0}
  .tier-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:18px;margin-top:8px}
  .tier-card{background:var(--white);border:1px solid var(--border);border-radius:var(--radius-lg);padding:26px 22px 22px;display:flex;flex-direction:column;position:relative;transition:transform 0.25s var(--ease),box-shadow 0.25s var(--ease),border-color 0.25s var(--ease)}
  .tier-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:var(--gold-light)}
  .tier-card.tier-current{border-color:var(--gold);background:linear-gradient(180deg,var(--white) 0%,var(--cream) 100%);box-shadow:var(--shadow-gold)}
  .tier-card.tier-recommended::before{content:'Most Popular';position:absolute;top:-11px;left:50%;transform:translateX(-50%);background:var(--gold);color:var(--white);font-size:10px;letter-spacing:0.14em;text-transform:uppercase;font-weight:500;padding:4px 12px;border-radius:99px;font-family:var(--font-body)}
  .tier-name{font-family:var(--font-display);font-size:28px;font-weight:400;color:var(--charcoal);margin-bottom:4px;letter-spacing:-0.01em}
  .tier-tagline{font-size:12px;color:var(--muted);line-height:1.5;margin-bottom:18px;min-height:32px}
  .tier-price{display:flex;align-items:baseline;gap:4px;margin-bottom:22px;padding-bottom:18px;border-bottom:1px solid var(--border-soft)}
  .tier-price-num{font-family:var(--font-display);font-size:44px;font-weight:300;color:var(--charcoal);line-height:1}
  .tier-price-unit{font-size:13px;color:var(--muted);font-weight:300}
  .tier-features{list-style:none;padding:0;margin:0 0 22px;flex:1;display:flex;flex-direction:column;gap:11px}
  .tier-features li{font-size:13px;color:var(--charcoal2);display:flex;align-items:flex-start;gap:9px;line-height:1.45}
  .tier-features li::before{content:'';width:5px;height:5px;border-radius:50%;background:var(--gold);flex-shrink:0;margin-top:7px}
  .tier-features li.tier-feat-strong{color:var(--charcoal);font-weight:500}
  .tier-cta{width:100%;padding:11px 14px;font-size:13px;letter-spacing:0.06em}
  .usage-row{display:flex;justify-content:space-between;align-items:center;padding:11px 0;border-bottom:1px solid var(--border-soft);font-size:13px}
  .usage-row:last-child{border-bottom:none}
  .usage-label{color:var(--charcoal3)}
  .usage-value{font-family:var(--font-display);font-size:18px;font-weight:400;color:var(--charcoal)}
  .usage-value-warn{color:var(--gold-deep)}
  .usage-value-err{color:var(--error)}
  .usage-bar{height:4px;background:var(--cream2);border-radius:2px;overflow:hidden;margin-top:6px}
  .usage-bar-fill{height:100%;background:var(--gold);transition:width 0.4s var(--ease)}
  .usage-bar-fill.warn{background:#D4A85E}
  .usage-bar-fill.err{background:var(--error)}
  .paywall-overlay{position:fixed;inset:0;background:rgba(44,40,37,0.55);backdrop-filter:blur(6px);z-index:1000;display:flex;align-items:center;justify-content:center;padding:24px;animation:fadeIn 0.3s var(--ease)}
  @keyframes fadeIn{from{opacity:0}to{opacity:1}}
  .paywall-card{background:var(--cream);border-radius:var(--radius-xl);max-width:780px;width:100%;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg);padding:36px 32px;animation:slideUp 0.35s var(--ease)}
  @keyframes slideUp{from{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}
  .paywall-title{font-family:var(--font-display);font-size:34px;font-weight:400;color:var(--charcoal);text-align:center;margin-bottom:6px;letter-spacing:-0.01em}
  .paywall-sub{font-size:13px;color:var(--muted);text-align:center;margin-bottom:28px;line-height:1.6}
  @media (max-width:640px){
    .paywall-card{padding:26px 20px}
    .paywall-title{font-size:26px}
    .tier-grid{grid-template-columns:1fr;gap:14px}
  }

  /* ─── UTILITY CLASSES ──────────────────────────────────────────────────
     These replace the most-repeated inline style="..." attributes. Naming
     is semantic where possible (e.g. .u-eyebrow names the 10px uppercase
     label pattern) and utility-style otherwise (.u-muted-xs). The "u-"
     prefix keeps them visually grouped and avoids clashing with the named
     component classes (.btn, .auth-card, etc.) above. */
  .u-muted-xs{font-size:11px;color:var(--muted)}
  .u-muted-sm{font-size:13px;color:var(--muted)}
  .u-muted-light{color:var(--muted);font-weight:300}
  .u-eyebrow{font-size:10px;letter-spacing:0.12em;text-transform:uppercase;color:var(--muted);margin-bottom:4px;font-weight:500}
  .u-gold-strong{color:var(--gold-dark);font-weight:500}
  .u-gold{color:var(--gold-dark)}
  .u-card-soft{background:var(--cream);border:1px solid var(--border);border-radius:var(--radius);padding:14px}
  .u-panel-section{padding:16px;border-top:1px solid var(--border);background:var(--cream2)}
  .u-flex-fill{flex:1;min-width:0}
  .u-row-center{display:flex;align-items:center;gap:10px}
  .u-input{width:100%;padding:8px 12px;border:1px solid var(--border);border-radius:var(--radius);font-family:var(--font-body);font-size:14px;background:var(--white)}
  /* small button-size variants */
  .u-btn-sm{padding:6px 14px;font-size:12px}
  .u-btn-xs{padding:5px 12px;font-size:11px}
  .u-btn-md{padding:7px 16px;font-size:12px}

  /* ─── SEPARATED LIST ROWS ─────────────────────────────────────────────
     Project lists previously rendered as one continuous bordered card with
     hairline dividers between rows — this made independent events read as
     "connected" to each other. The list-stack pattern below gives each row
     its own card so they sit as separate, independent objects in a column,
     while keeping a quiet visual rhythm via the gap. */
  .list-stack{display:flex;flex-direction:column;gap:10px}
  .list-card{
    background:var(--white);
    border:1px solid var(--border);
    border-radius:var(--radius-lg);
    box-shadow:var(--shadow-xs);
    overflow:hidden;
    transition:box-shadow .15s var(--ease),transform .15s var(--ease),border-color .15s var(--ease);
  }
  .list-card:hover{
    box-shadow:var(--shadow);
    border-color:var(--gold-light);
    transform:translateY(-1px);
  }

  /* ─── PAGINATION ──────────────────────────────────────────────────────
     Editorial-feeling page picker — numeric pills with ‹ / › arrows.
     Used across every paginated list (projects, invoices, contractors,
     inbox, books). Centered with a thin rule of summary text above it
     ("Showing 1–10 of 47"). */
  .pager{display:flex;flex-direction:column;align-items:center;gap:10px;padding:18px 12px 6px;margin-top:12px}
  .pager-summary{font-size:11px;letter-spacing:0.1em;text-transform:uppercase;color:var(--muted);font-weight:500}
  .pager-controls{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:center}
  .pager-btn{
    min-width:32px;height:32px;padding:0 10px;
    background:var(--white);border:1px solid var(--border);border-radius:var(--radius);
    font-family:var(--font-body);font-size:13px;color:var(--charcoal2);font-weight:500;
    cursor:pointer;transition:all .12s var(--ease);
    display:inline-flex;align-items:center;justify-content:center;
  }
  .pager-btn:hover:not(:disabled):not(.active){background:var(--cream);border-color:var(--gold-light)}
  .pager-btn.active{background:var(--charcoal);color:var(--cream);border-color:var(--charcoal);cursor:default}
  .pager-btn:disabled{opacity:0.35;cursor:not-allowed}
  .pager-ellipsis{padding:0 6px;color:var(--muted);font-size:13px;user-select:none}

  /* ═══════════════════════════════════════════════════════════════════════
     UTILITY CLASSES — extracted from inline style="..." attrs
     ───────────────────────────────────────────────────────────────────────
     Each class below corresponds to a pattern that was repeated 5+ times
     in app.js. Naming:
       .u-*          single-purpose utility (one or two properties)
       .row-* /.stack-*  flex layout primitives
       .heading-*    semantic display-font heading
       .label-* /.note-* /.amount-*  typography patterns
       .btn-pill /.btn-compact  size variants on .btn
       .summary-row        the "Subtotal: $X" row
     ═══════════════════════════════════════════════════════════════════════ */

  /* Flex layout primitives */
  .row{display:flex;align-items:center;gap:8px}
  .row-baseline{display:flex;align-items:baseline;gap:3px}
  .row-gap-wrap{display:flex;gap:8px;flex-wrap:wrap}
  .stack{display:flex;flex-direction:column;gap:8px}

  /* Spacing utilities */
  .u-mb-0{margin-bottom:0}
  .u-mb-4{margin-bottom:4px}
  .u-mb-6{margin-bottom:6px}
  .u-mb-8{margin-bottom:8px}
  .u-mb-12{margin-bottom:12px}
  .u-mb-14{margin-bottom:14px}
  .u-mb-16{margin-bottom:16px}
  .u-mb-20{margin-bottom:20px}
  .u-mt-0{margin-top:0}
  .u-mt-8{margin-top:8px}
  .u-mt-10{margin-top:10px}
  .u-mt-12{margin-top:12px}
  .u-mt-16{margin-top:16px}
  .u-p-0{padding:0}

  /* Text-align utilities */
  .u-text-center{text-align:center}
  .u-text-right{text-align:right}

  /* Typography utilities */
  .u-fw-500{font-weight:500}
  .u-fw-600{font-weight:600}
  .u-cursor-pointer{cursor:pointer}
  .u-flex-1{flex:1}
  .u-color-charcoal{color:var(--charcoal)}
  .u-color-charcoal-2{color:var(--charcoal2)}
  .u-color-charcoal-3{color:var(--charcoal3)}
  .u-color-muted{color:var(--muted)}
  .u-color-error{color:var(--error)}
  .u-muted-12{font-size:12px;color:var(--muted)}

  /* Semantic typography patterns */
  .label-section{display:block;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--muted);font-weight:500;margin-bottom:6px}
  .label-accent{font-size:11px;color:var(--gold-dark);font-weight:500}
  .note-soft{color:var(--muted);font-style:italic}
  .row-meta{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--charcoal2)}
  .amount-label{color:var(--gold-dark);font-weight:600;flex-shrink:0}

  /* Display-font headings (Cormorant) */
  .heading-lg{font-family:var(--font-display);font-size:22px;font-weight:300;color:var(--charcoal)}
  .heading-md{font-family:var(--font-display);font-size:20px;font-weight:300;color:var(--charcoal)}
  .heading-md-muted{font-family:var(--font-display);font-size:20px;font-weight:300;color:var(--muted);letter-spacing:0}

  /* Button size variants — apply alongside .btn .btn-outline etc. */
  .btn-pill{padding:4px 10px;font-size:11px}
  .btn-pill-mr{padding:5px 12px;font-size:11px;margin-left:4px}
  .btn-compact{padding:6px 14px;font-size:11px;flex-shrink:0}

  /* Invoice/estimate "Subtotal: $X" summary row (was 6× inline) */
  .summary-row{display:flex;justify-content:space-between;font-size:13px;color:var(--charcoal2);padding:4px 0}
  .summary-row-spaced{margin-top:10px}
/* ═══════════════════════════════════════════════════════════════════════
   RUN SHEET — TIMELINE RIBBON
   Replaces the .rs-tbl table layout. Each block is a card on a vertical
   gold rail. Cards collapse to a one-line read view and expand inline
   to reveal chip pickers — no native <select> in this panel anymore.
   The old .rs-tbl rules above are kept for the export/print path.
   ═══════════════════════════════════════════════════════════════════ */

  /* ── Anchor banner ─────────────────────────────────────────────────
     Sticky-feel context bar at the top of the panel. Shows the three
     time anchors (start of day, ceremony, ready-by) and the buffer
     control. Cormorant display serif on the time numbers gives it the
     wedding-program feel without using actual cards. */
  .rs-anchor{
    display:flex;align-items:center;gap:18px;
    flex-wrap:wrap;
    padding:14px 18px;background:var(--cream);
    border:1px solid var(--border-soft);border-radius:var(--radius-lg);
    margin-bottom:16px;box-shadow:var(--shadow-xs);
  }
  .rs-anchor-stats{display:flex;align-items:center;gap:22px;flex-wrap:wrap;flex:1 1 auto}
  .rs-anchor-stats > .rs-anchor-build{margin-left:auto}
  .rs-anchor-stat{display:flex;flex-direction:column;gap:3px;min-width:60px}
  .rs-anchor-stat-label{
    font-size:10px;letter-spacing:0.14em;text-transform:uppercase;
    color:var(--muted);font-weight:500
  }
  .rs-anchor-stat-value{
    font-family:var(--font-display);font-size:24px;line-height:1;
    color:var(--charcoal);font-weight:500;
    display:inline-flex;align-items:baseline;gap:5px
  }
  .rs-anchor-stat-value-gold{color:var(--gold-deep)}
  .rs-anchor-hm{font-variant-numeric:tabular-nums}
  .rs-anchor-ampm{
    font-family:var(--font-body);font-size:11px;letter-spacing:0.5px;
    color:var(--muted);font-weight:500
  }
  .rs-anchor-divider{width:1px;height:32px;background:var(--border)}
  .rs-anchor-time-input{
    padding:4px 7px;border:1px solid var(--border);
    border-radius:var(--radius);font-family:var(--font-body);
    font-size:13px;background:var(--white);font-weight:600;width:108px
  }
  .rs-anchor-buffer{display:inline-flex;align-items:center;gap:5px;margin-top:2px}
  .rs-anchor-buffer-input{
    width:48px;padding:4px 7px;border:1px solid var(--border);
    border-radius:var(--radius);font-family:var(--font-body);
    font-size:13px;background:var(--white);text-align:right
  }
  .rs-anchor-build{
    padding:8px 16px;font-size:12px;
    display:inline-flex;align-items:center;gap:6px;flex-shrink:0
  }

  /* ── Conflict summary bar ──────────────────────────────────────────
     Sits between the anchor and the ribbon when there are overlaps.
     Same gold-soft palette as the original — we read the *individual*
     conflicting cards via .rs-row-conflict instead. */
  .rs-conflict-bar{
    background:rgba(184,58,44,0.06);
    border:1px solid rgba(184,58,44,0.25);
    border-radius:var(--radius);
    padding:9px 13px;margin-bottom:14px;
    font-size:12px;color:var(--charcoal2)
  }
  .rs-conflict-bar strong{color:var(--error)}

  /* ── Build layout: reference pane + timeline ────────────────────
     Two-column grid. The aside (party + team) is the director's
     reference while wiring blocks, sticky on desktop so it scrolls
     with the ribbon. Below the breakpoint the aside stacks above. */
  .rs-build{
    display:grid;
    grid-template-columns:minmax(220px, 280px) 1fr;
    gap:18px;
    align-items:start
  }
  @media (max-width: 860px){
    .rs-build{grid-template-columns:1fr}
  }
  .rs-build-aside{
    display:flex;flex-direction:column;gap:14px;
    position:sticky;top:12px;
    align-self:start
  }
  @media (max-width: 860px){
    .rs-build-aside{position:static}
  }
  .rs-build-main{min-width:0}  /* let the ribbon shrink instead of overflowing */

  /* Reference pane sections — same shell shape for Party and Team. */
  .rs-pane-section{
    background:var(--cream);
    border:1px solid var(--border-soft);
    border-radius:var(--radius);
    padding:12px 14px
  }
  .rs-pane-section-head{
    display:flex;align-items:center;gap:8px;
    margin-bottom:10px
  }
  .rs-pane-section-title{
    font-size:11px;letter-spacing:0.08em;text-transform:uppercase;
    color:var(--muted);font-weight:600
  }
  .rs-pane-section-count{
    display:inline-flex;align-items:center;justify-content:center;
    min-width:20px;height:18px;padding:0 6px;
    background:var(--white);border:1px solid var(--border);
    border-radius:10px;font-size:10px;color:var(--charcoal2);
    font-weight:600;font-variant-numeric:tabular-nums
  }
  .rs-partysize-input{
    width:100%;
    min-height:60px;
    padding:8px 10px;
    border:1px solid var(--border);
    border-radius:var(--radius);
    font-family:var(--font-body);font-size:12.5px;
    color:var(--charcoal);background:var(--white);
    line-height:1.45;resize:vertical;
    box-sizing:border-box;outline:none
  }
  .rs-partysize-input:focus{border-color:var(--gold)}

  /* Team list rows — avatar + name + class chips. Compact: this is a
     reference, not an action surface. Assignment still happens on the
     block cards via the existing stylist chip-row. */
  .rs-team-list{
    list-style:none;margin:0;padding:0;
    display:flex;flex-direction:column;gap:8px
  }
  .rs-team-row{
    display:flex;align-items:flex-start;gap:9px;
    padding:6px 4px;
    border-bottom:1px solid var(--border-soft)
  }
  .rs-team-row:last-child{border-bottom:none}
  .rs-team-avatar{
    flex-shrink:0;
    width:26px;height:26px;border-radius:50%;
    display:inline-flex;align-items:center;justify-content:center;
    background:var(--white);border:1px solid var(--border);
    font-size:10px;font-weight:600;color:var(--charcoal2);
    letter-spacing:0.04em
  }
  .rs-team-meta{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
  .rs-team-name{
    font-size:12.5px;color:var(--charcoal);font-weight:500;line-height:1.3;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap
  }
  .rs-team-you{
    display:inline-block;padding:1px 5px;margin-left:4px;
    background:rgba(201,169,110,0.16);color:var(--gold-deep);
    border-radius:6px;font-size:9px;font-weight:600;
    letter-spacing:0.04em;text-transform:uppercase;vertical-align:middle
  }
  .rs-team-classes{display:flex;flex-wrap:wrap;gap:4px}
  .rs-team-class-chip{
    display:inline-flex;align-items:center;
    padding:1px 7px;
    background:var(--white);border:1px solid var(--border);
    border-radius:10px;font-size:10px;color:var(--muted);
    line-height:1.5
  }
  .rs-team-sub{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
  .rs-team-load{
    display:inline-flex;align-items:center;
    padding:1px 7px;
    background:rgba(46,125,94,0.10);
    border:1px solid rgba(46,125,94,0.30);
    color:var(--success);
    border-radius:10px;font-size:10px;
    font-weight:600;letter-spacing:0.02em;
    line-height:1.5
  }
  .rs-team-empty{
    font-size:11.5px;color:var(--muted);font-style:italic;
    line-height:1.5
  }

  /* ── Party-members collapsible (legacy class kept for any other
     consumers; the panel now uses the always-visible pane above). */
  .rs-party-details{
    margin-bottom:18px;background:var(--cream);
    border:1px solid var(--border-soft);
    border-radius:var(--radius);padding:10px 14px
  }
  .rs-party-summary{
    cursor:pointer;font-size:11px;letter-spacing:0.08em;
    text-transform:uppercase;color:var(--muted);font-weight:600;
    outline:none;list-style:none
  }
  .rs-party-summary-hint{
    color:var(--muted);font-weight:400;letter-spacing:0;
    text-transform:none;margin-left:4px
  }
  .rs-party-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
  .rs-party-chip{
    display:inline-flex;align-items:center;gap:6px;
    padding:4px 4px 4px 10px;
    background:var(--white);border:1px solid var(--border);
    border-radius:20px;font-size:12px
  }
  .rs-party-chip-bride{
    background:rgba(201,169,110,0.14);border-color:var(--gold)
  }
  .rs-party-chip-x{
    background:transparent;border:none;cursor:pointer;
    color:var(--muted);font-size:14px;line-height:1;padding:0 6px 0 2px
  }
  .rs-party-empty{margin-bottom:10px}
  .rs-party-empty-hint{
    font-size:12px;color:var(--muted);font-style:italic;margin-bottom:8px
  }
  .rs-party-quickadd{display:flex;flex-wrap:wrap;gap:6px}
  .rs-party-quickadd-label{
    font-size:10px;letter-spacing:0.08em;text-transform:uppercase;
    color:var(--muted);font-weight:600;align-self:center
  }
  .rs-party-quickadd-btn{
    display:inline-flex;align-items:center;gap:5px;
    padding:4px 11px;background:var(--white);
    border:1px solid var(--border);border-radius:20px;
    font-size:12px;cursor:pointer;font-family:var(--font-body);
    color:var(--charcoal2);
    transition:border-color .15s,background .15s
  }
  .rs-party-quickadd-btn:hover{
    border-color:var(--gold-light);background:rgba(201,169,110,0.06)
  }
  .rs-party-addrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
  .rs-party-add-input{
    flex:1;min-width:180px;padding:6px 10px;
    border:1px solid var(--border);border-radius:var(--radius);
    font-family:var(--font-body);font-size:13px;background:var(--white)
  }
  .rs-party-bride-toggle{
    display:inline-flex;align-items:center;gap:5px;
    font-size:12px;color:var(--charcoal2)
  }
  .rs-party-bride-toggle input{accent-color:var(--gold)}

  /* ── The ribbon ──────────────────────────────────────────────────
     Vertical gold hairline rail on the left. Each .rs-row is a single
     timestamp + dot + card, laid out as a grid so the rail stays
     perfectly aligned no matter the card height. */
  .rs-ribbon{
    position:relative;
    display:flex;flex-direction:column;gap:12px;
    padding:6px 0 6px 108px;
    margin-bottom:14px
  }
  .rs-ribbon::before{
    content:"";position:absolute;left:82px;top:14px;bottom:14px;
    width:1px;background:var(--border)
  }

  .rs-row{position:relative}

  /* Rail label — sits to the LEFT of the dot with a clear gap.
     hm + ampm stacked vertically, right-aligned toward the rail line. */
  .rs-rail-label{
    position:absolute;left:-108px;top:10px;width:70px;text-align:right;
    line-height:1;display:flex;flex-direction:column;align-items:flex-end;gap:2px
  }
  .rs-rail-hm{
    font-family:var(--font-display);font-size:20px;
    color:var(--charcoal);font-weight:500;
    font-variant-numeric:tabular-nums;display:block
  }
  .rs-rail-hm-active{color:var(--gold-deep)}
  .rs-rail-ampm{
    font-family:var(--font-body);font-size:10px;
    letter-spacing:0.5px;color:var(--muted);font-weight:500;display:block
  }
  .rs-rail-dot{
    position:absolute;left:-30px;top:18px;
    width:9px;height:9px;border-radius:50%;
    background:var(--white);border:2px solid var(--gold);
    transition:transform .18s var(--ease)
  }
  .rs-rail-dot-active{
    width:11px;height:11px;
    background:var(--gold);border-color:var(--gold-dark)
  }
  .rs-rail-dot-conflict{
    border-color:var(--error);background:var(--white)
  }

  /* ── The card itself ─────────────────────────────────────────────
     Collapsed: single flex row, click anywhere to open. Expanded:
     grows downward, fields appear in sections below the top row. */
  .rs-card{
    background:var(--cream);
    border-radius:var(--radius-lg);
    padding:14px 18px;
    transition:border-color .18s var(--ease), box-shadow .18s var(--ease), transform .18s var(--ease);
    cursor:pointer
  }
  .rs-card:not(.rs-card-open){display:flex;align-items:center;gap:14px}
  .rs-card:not(.rs-card-open):hover{
    border-color:var(--gold-light) !important;
    transform:translateY(-1px);
    box-shadow:var(--shadow) !important
  }
  .rs-card-open{cursor:default}

  .rs-card-body{flex:1;min-width:0}
  .rs-card-name{
    font-family:var(--font-display);font-size:22px;line-height:1.1;
    color:var(--charcoal);display:inline-flex;align-items:center;gap:7px
  }
  .rs-card-meta-row{
    margin-top:5px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;
    font-size:12px;color:var(--charcoal3)
  }
  .rs-card-meta em{font-style:italic;color:var(--charcoal2);font-weight:500}
  .rs-card-sep{color:var(--muted)}
  .rs-card-endtime{
    font-family:var(--font-display);font-size:16px;color:var(--muted);
    font-style:italic;flex-shrink:0
  }
  .rs-card-x{
    background:transparent;border:none;cursor:pointer;
    color:var(--muted2);font-size:18px;line-height:1;
    padding:2px 4px;flex-shrink:0;
    transition:color .15s
  }
  .rs-card-x:hover{color:var(--error)}

  /* Bride star — gold, used inline next to bride names everywhere */
  .rs-bride-star{color:var(--gold);font-size:13px;line-height:1}

  /* Empty/placeholder text — same in both states */
  .rs-card .rs-empty,.rs-empty{color:var(--muted);font-style:italic}

  /* Conflict ring on the card — already set inline via cardBorder, but
     this lets us soften the hover so it doesn't override the warning. */
  .rs-row-conflict .rs-card:hover{
    border-color:var(--error) !important
  }

  /* ── Chips (read-mode small chip in card-body) ───────────────── */
  .rs-chip{
    display:inline-flex;align-items:center;gap:5px;
    padding:4px 10px;border-radius:var(--radius);
    font-size:12px;font-weight:500;letter-spacing:0.2px;
    font-family:var(--font-body);
    line-height:1.3
  }
  .rs-chip-service{
    background:var(--white);color:var(--gold-deep);border:1px solid var(--gold-light)
  }
  .rs-chip-empty{
    background:transparent;border:1px dashed var(--border);
    color:var(--muted);font-weight:400;font-style:italic
  }
  .rs-chip-tag{
    margin-left:4px;font-size:9px;letter-spacing:0.6px;
    text-transform:uppercase;color:var(--muted);font-weight:500
  }

  /* ── Expanded edit view ──────────────────────────────────────── */
  .rs-edit-toprow{
    display:grid;
    grid-template-columns:auto auto 1fr auto;
    gap:14px;align-items:end;
    padding-bottom:12px;border-bottom:1px solid var(--border-soft);
    margin-bottom:12px
  }
  .rs-edit-label{
    display:flex;flex-direction:column;gap:4px;font-size:10px;
    letter-spacing:0.14em;text-transform:uppercase;
    color:var(--muted);font-weight:500
  }
  .rs-edit-time{
    padding:6px 8px;border:1px solid var(--border);
    border-radius:var(--radius);font-family:var(--font-body);
    font-size:14px;background:var(--white);font-weight:600;
    width:108px
  }
  .rs-edit-duration{display:inline-flex;align-items:center;gap:5px}
  .rs-edit-dur-input{
    width:58px;padding:6px 8px;border:1px solid var(--border);
    border-radius:var(--radius);font-family:var(--font-body);
    font-size:14px;background:var(--white);text-align:right
  }
  .rs-edit-endtime{
    font-size:13px;color:var(--muted);font-style:italic;align-self:center
  }
  .rs-edit-actions{
    display:flex;align-items:center;gap:6px;align-self:center
  }
  .rs-edit-done{
    background:var(--gold);color:var(--white);
    border:none;padding:7px 16px;border-radius:var(--radius);
    font-family:var(--font-body);font-size:12px;font-weight:500;
    letter-spacing:0.5px;cursor:pointer;
    transition:background .15s
  }
  .rs-edit-done:hover{background:var(--gold-dark)}
  .rs-edit-trash{
    background:transparent;border:none;cursor:pointer;
    color:var(--muted2);font-size:20px;line-height:1;
    padding:4px 8px;
    transition:color .15s
  }
  .rs-edit-trash:hover{color:var(--error)}

  .rs-edit-section{margin-bottom:14px}
  .rs-edit-section:last-child{margin-bottom:0}
  .rs-edit-section-label{
    font-size:10px;letter-spacing:0.14em;text-transform:uppercase;
    color:var(--muted);font-weight:600;margin-bottom:8px
  }
  .rs-chip-row{display:flex;gap:6px;flex-wrap:wrap;align-items:center}

  /* Pickable chip in expanded mode — outlined, active=gold-filled */
  .rs-chip-pick{
    background:var(--white);border:1px solid var(--border);
    color:var(--charcoal2);padding:6px 12px;border-radius:var(--radius);
    font-family:var(--font-body);font-size:12px;font-weight:500;
    cursor:pointer;line-height:1.3;
    display:inline-flex;align-items:center;gap:5px;
    transition:border-color .15s,background .15s,color .15s
  }
  .rs-chip-pick:hover{
    border-color:var(--gold-light);
    background:rgba(201,169,110,0.06)
  }
  .rs-chip-active{
    background:var(--gold);border-color:var(--gold);color:var(--white)
  }
  .rs-chip-active:hover{
    background:var(--gold-dark);border-color:var(--gold-dark);color:var(--white)
  }
  .rs-chip-active .rs-bride-star,.rs-chip-active .rs-chip-tag{color:var(--cream2)}

  /* Stylist avatar inside chip */
  .rs-avatar{
    width:20px;height:20px;border-radius:50%;
    background:var(--gold-light);color:var(--gold-deep);
    font-size:9px;font-weight:600;letter-spacing:0.3px;
    display:inline-flex;align-items:center;justify-content:center;
    flex-shrink:0
  }
  .rs-chip-active .rs-avatar{
    background:var(--white);color:var(--gold-dark)
  }

  /* "Other…" free-text input under the person chip row */
  .rs-edit-text{
    margin-top:8px;padding:7px 10px;border:1px solid var(--border);
    border-radius:var(--radius);font-family:var(--font-body);
    font-size:13px;background:var(--white);width:100%;max-width:320px
  }

  /* Hint text when no party / no services / no stylists */
  .rs-edit-hint{
    font-size:12px;color:var(--muted);font-style:italic
  }

  /* Per-block conflict warning inside the expanded card */
  .rs-edit-warn{
    margin-top:8px;padding:7px 11px;
    background:rgba(184,58,44,0.06);
    border:1px solid rgba(184,58,44,0.25);
    border-radius:var(--radius);
    font-size:12px;color:var(--error);
    display:flex;align-items:center;gap:6px
  }
  .rs-edit-warn-icon{font-size:13px;line-height:1}

  /* ── Empty state ─────────────────────────────────────────────── */
  .rs-empty-state{
    text-align:center;padding:36px 20px;
    background:var(--cream);
    border:1px dashed var(--border);
    border-radius:var(--radius-lg);
    margin-bottom:14px
  }
  .rs-empty-icon{
    color:var(--gold);margin:0 auto 10px;
    width:32px;height:32px
  }
  .rs-empty-title{
    font-family:var(--font-display);font-size:20px;
    color:var(--charcoal);margin-bottom:6px
  }
  .rs-empty-hint{
    font-size:13px;color:var(--muted);max-width:380px;
    margin:0 auto 16px;line-height:1.5
  }
  .rs-empty-actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}

  /* ── Ready-by closer note ────────────────────────────────────── */
  .rs-readyby{
    background:rgba(201,169,110,0.08);
    border:1px solid var(--gold-light);
    border-radius:var(--radius);
    padding:10px 14px;margin-bottom:14px;
    font-size:13px;color:var(--charcoal2)
  }

  /* ── Footer actions ──────────────────────────────────────────── */
  .rs-footer-actions{
    display:flex;align-items:center;gap:10px;
    justify-content:space-between;flex-wrap:wrap
  }
  .rs-add-block-btn{padding:7px 18px;font-size:12px}
  .rs-export-btn{
    padding:6px 14px;font-size:12px;
    display:inline-flex;align-items:center;gap:6px
  }

  /* Day-of Schedule day tabs (top of panel when extra days exist) */
  .rs-day-tabs{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}
  .rs-day-tab{
    display:flex;flex-direction:column;gap:1px;padding:7px 14px;
    border:1px solid var(--border);background:var(--white);
    border-radius:var(--radius);cursor:pointer;text-align:left;
    min-width:118px;transition:all .12s;
  }
  .rs-day-tab.is-active{border-color:var(--gold-dark);background:rgba(201,169,110,0.12)}
  .rs-day-tab-name{font-size:12px;font-weight:600;color:var(--charcoal2)}
  .rs-day-tab.is-active .rs-day-tab-name{color:var(--charcoal)}
  .rs-day-tab-date{font-size:10px;color:var(--muted)}
  .rs-manage-days{
    display:inline-flex;align-items:center;gap:5px;padding:7px 11px;
    border:none;background:transparent;cursor:pointer;
    font-size:11px;color:var(--muted);transition:color .12s;
  }
  .rs-manage-days:hover{color:var(--gold-dark)}

  /* ── Mobile ──────────────────────────────────────────────────── */
  @media (max-width:640px){
    .rs-anchor{padding:12px 14px;gap:12px}
    .rs-anchor-stats{gap:14px}
    .rs-anchor-stat-value{font-size:20px}
    .rs-anchor-divider{display:none}
    /* Stack day tabs full-width on mobile so the date/time text breathes */
    .rs-day-tab{flex:1 1 100%;min-width:0}
    .rs-manage-days{margin-left:auto}
    .rs-ribbon{padding-left:84px}
    .rs-ribbon::before{left:62px}
    .rs-rail-label{left:-84px;width:54px}
    .rs-rail-hm{font-size:16px}
    .rs-rail-dot{left:-24px}
    .rs-card{padding:12px 14px}
    .rs-card-name{font-size:19px}
    .rs-card:not(.rs-card-open){flex-wrap:wrap}
    .rs-card-endtime{display:none}
    .rs-edit-toprow{grid-template-columns:1fr 1fr;gap:10px}
    .rs-edit-toprow .rs-edit-endtime{grid-column:1/-1}
    .rs-edit-toprow .rs-edit-actions{grid-column:1/-1;justify-content:flex-end}
  }
