/* ============================================================
   eCSyn — application stylesheet
   Extracted from header.php: this block is 100% static, so shipping
   it inline meant re-downloading ~26KB on every page view. As a file
   it is fetched once and served from cache thereafter.
   The :root custom properties stay inline in header.php because they
   are generated from theme_config.php per request.
   Cache-busted via ?v= on the link tag — bump it after editing.
   ============================================================ */
  *{box-sizing:border-box; margin:0; padding:0;}
  html{-webkit-text-size-adjust:100%;}
  /* App-shell layout: the whole frame is exactly viewport-height and
     does NOT scroll; only .scroll-body scrolls. The bottom nav is then
     a real flex row inside .main, so it cannot drift, detach, or
     depend on position:fixed resolving correctly. */
  html{height:100%;}
  body{font-family:var(--font-family); background:var(--page); color:var(--ink900);
       height:100vh; height:100dvh; overflow:hidden; display:flex;}
  a{-webkit-tap-highlight-color:transparent; color:inherit; text-decoration:none;}
  button{font-family:inherit; border:none; background:none; cursor:pointer; color:inherit;}
  input,select,textarea{font-family:inherit;}

  /* ---- icons ---- */
  .icon{width:18px; height:18px; stroke:currentColor; fill:none; stroke-width:1.8;
        stroke-linecap:round; stroke-linejoin:round; display:block; flex-shrink:0;}
  .icon-sm{width:14px; height:14px;}
  /* The funnel's stem is narrower than the other glyphs, so at the shared
     weight its outline closes up and reads as a solid blob. Extra weight
     only here; colour is inherited so it matches every other nav icon. */
  .icon-funnel{stroke-width:2.3;}
  .icon-lg{width:22px; height:22px;}
  .icon-tile{width:38px; height:38px; border-radius:11px; background:var(--g50); color:var(--g700);
             display:flex; align-items:center; justify-content:center; flex-shrink:0;}
  .icon-tile.on-brand{background:rgba(255,255,255,0.16); color:#fff;}
  .icon-tile.sm{width:32px; height:32px; border-radius:9px;}

  /* ---- desktop rail ---- */
  .rail{
    width:var(--rail-w); background:var(--g700); display:none; flex-direction:column;
    align-items:center; padding:16px 0; gap:6px; flex-shrink:0; height:100%; overflow-y:auto;
  }
  .rail .logo{width:36px; height:36px; border-radius:10px; background:var(--g600); color:#fff;
              display:flex; align-items:center; justify-content:center; font-weight:700;
              font-size:calc(14px * var(--font-scale)); margin-bottom:16px;}
  .rail a{width:52px; height:52px; border-radius:13px; display:flex; align-items:center;
          justify-content:center; color:var(--g200); opacity:.85;}
  .rail a .icon{width:26px; height:26px;}
  .rail a.active{background:var(--g600); color:#fff; opacity:1;}
  .rail a:hover{opacity:1;}
  .rail .spacer{flex:1;}

  .main{flex:1; min-width:0; min-height:0; display:flex; flex-direction:column; position:relative;}

  /* ---- topbar ---- */
  .topbar{background:var(--card); border-bottom:1px solid var(--line);
          display:flex; align-items:center; justify-content:space-between;
          padding:14px 20px; flex-shrink:0; z-index:20; gap:14px;}
  .brand{font-weight:700; font-size:calc(16px * var(--font-scale)); color:var(--g900);}
  .backlink{display:flex; align-items:center; gap:6px; font-size:calc(13px * var(--font-scale));
            font-weight:600; color:var(--ink600);}
  .topbar .push{flex:1;}
  .avatar-sm{width:30px; height:30px; border-radius:50%;
             background:linear-gradient(135deg,var(--g600),var(--g900)); color:#fff;
             display:flex; align-items:center; justify-content:center;
             font-size:calc(11px * var(--font-scale)); font-weight:700; flex-shrink:0;}

  .scroll-body{flex:1; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch;
               /* Horizontal page scroll is never wanted here — a wide child
                  (the pipeline board, a long table) must scroll inside its
                  own box rather than dragging the whole layout sideways. */
               overflow-x:hidden;
               width:100%;
               padding:20px max(32px, (100% - 1200px)/2) 28px;
               scrollbar-width:thin; scrollbar-color:var(--line) transparent;}
  .scroll-body::-webkit-scrollbar{width:10px;}
  .scroll-body::-webkit-scrollbar-track{background:transparent;}
  .scroll-body::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;
               border:2px solid var(--page); background-clip:padding-box;}
  .scroll-body::-webkit-scrollbar-thumb:hover{background:var(--ink400); background-clip:padding-box;}

  /* ---- page head ---- */
  .page-head{display:flex; align-items:baseline; gap:10px; margin-bottom:16px; flex-wrap:wrap;}
  .page-head h1{font-size:calc(20px * var(--font-scale)); font-weight:700;}
  .page-head .sub{font-size:calc(12.5px * var(--font-scale)); color:var(--ink600);}

  /* ================= OLD SYSTEM (restored) ================= */
  .grid{display:grid; grid-template-columns:repeat(4,1fr); gap:16px;}
  .grid.g3{grid-template-columns:repeat(3,1fr);}
  .grid.g2{grid-template-columns:repeat(2,1fr);}
  .card{background:var(--card); border:1px solid var(--line); border-radius:12px;
        padding:16px; display:flex; flex-direction:column; min-width:0;}
  .card.wide{grid-column:span 2;}
  .card.full{grid-column:1/-1;}
  .card-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; gap:8px;}
  .card-head h3{font-size:calc(13px * var(--font-scale)); font-weight:600;}
  .hero{background:linear-gradient(135deg,var(--g900),var(--g700)); color:#fff; border:none;}
  .hero .label{font-size:calc(12px * var(--font-scale)); color:var(--g100); font-weight:500;}
  .hero .big{font-size:calc(30px * var(--font-scale)); font-weight:700; margin:8px 0 4px;}
  .hero .sub{font-size:calc(12px * var(--font-scale)); color:var(--g100);}
  .chart-box{position:relative; height:170px;}
  .chart-box.gauge{height:140px;}
  .chart-box.donut{height:190px;}
  .gauge-num{position:absolute; left:0; right:0; bottom:6px; text-align:center;
             font-size:calc(20px * var(--font-scale)); font-weight:700; color:var(--g800);}
  canvas{max-width:100%; display:block;}
  .rep{display:flex; align-items:center; gap:10px; padding:7px 0;}
  .rep .av{width:30px; height:30px; border-radius:50%; background:var(--g100); color:var(--g800);
           display:flex; align-items:center; justify-content:center;
           font-size:calc(11px * var(--font-scale)); font-weight:600; flex-shrink:0;}
  .rep .name{font-size:calc(13px * var(--font-scale)); flex:1; min-width:0;
             white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .rep .val{font-size:calc(13px * var(--font-scale)); font-weight:600; color:var(--g700);}
  .stat-alert{font-size:calc(26px * var(--font-scale)); font-weight:700; color:var(--amber);}
  .stat-alert-label{font-size:calc(11px * var(--font-scale)); color:var(--ink400); margin-top:2px;}
  .stat-sub{font-size:calc(11.5px * var(--font-scale)); color:var(--ink600); margin-top:auto; padding-top:8px;}
  .tag{font-size:calc(9.5px * var(--font-scale)); font-weight:700; padding:2px 7px;
       border-radius:5px; background:var(--g50); color:var(--g700);}

  /* ================= V2 SYSTEM (kept) ================= */
  .capture-hero{margin:0 0 18px;}
  .capture-hero h2{font-size:calc(22px * var(--font-scale)); font-weight:700; line-height:1.2;}
  .capture-hero .sub{font-size:calc(12.5px * var(--font-scale)); color:var(--ink600); margin-top:4px;}

  .method-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:10px; margin-bottom:22px;}
  .method-tile{background:var(--card); border:1px solid var(--line); border-radius:14px; padding:14px;
               display:flex; flex-direction:column; gap:10px; transition:border-color .15s ease;}
  .method-tile:hover{border-color:var(--g400);}
  .method-tile .lbl{font-size:calc(12.5px * var(--font-scale)); font-weight:600;}
  .method-tile .sub{font-size:calc(10.5px * var(--font-scale)); color:var(--ink400);}
  .method-tile.disabled{opacity:.5;}

  /* ---- channel cards: icon + status + title + explanation + action ---- */
  .ch-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:24px;}
  .ch-card{background:var(--card); border:1px solid var(--line); border-radius:14px;
           padding:28px 16px; display:flex; flex-direction:column; min-width:0;
           position:relative;}
  .ch-card.on{background:var(--card); border-color:var(--g200); cursor:pointer;}
  /* The CTA link's ::after is stretched over the whole card, so clicking
     anywhere in an available card follows the same href. "Coming soon"
     cards use .ch-act.off (a span, not a link) and stay inert. */
  .ch-card .ch-act.go::after{content:''; position:absolute; inset:0; border-radius:14px;}
  .ch-top{display:flex; flex-direction:column; align-items:center; margin-bottom:14px; gap:12px;}
  .ch-card{text-align:center; align-items:center; transition:transform .15s ease, box-shadow .15s ease, border-color .15s ease;}
  .ch-card.on:hover{border-color:var(--g400);}
  .ch-card:hover{transform:translateY(-3px); box-shadow:0 14px 28px -12px rgba(28,72,95,.25);}
  .ch-card .icon-tile{
    width:auto; height:auto; border-radius:0;
    background:none; border:none;
  }
  .ch-card .icon-tile .icon{width:52px; height:52px; stroke:var(--g700); stroke-width:1.6; fill:none;}
  .ch-card.on .icon-tile{background:none; border:none;}
  .ch-card.on .icon-tile .icon{stroke:var(--g700);}
  .ch-card h4{font-size:calc(15.5px * var(--font-scale)); font-weight:700; margin-bottom:4px;}
  .ch-card p{font-size:calc(12px * var(--font-scale)); color:var(--ink600);
             line-height:1.4; margin-bottom:14px; flex:1;}
  .ch-card .ch-act{width:100%;}
  .ch-badge{font-size:calc(10px * var(--font-scale)); font-weight:700; padding:4px 10px;
            border-radius:6px; white-space:nowrap; flex-shrink:0;}
  .ch-badge.live{background:var(--g100); color:var(--g800);}
  .ch-badge.soon{background:var(--page); color:var(--ink400); border:1px solid var(--line);}
  .ch-act{display:block; text-align:center; padding:11px; border-radius:9px;
          font-size:calc(13px * var(--font-scale)); font-weight:700;}
  .ch-act.go{background:var(--g700); color:#fff;}
  .ch-act.go:hover{background:var(--g800);}
  .ch-act.manage{color:var(--g700); background:transparent; padding:6px 0; text-align:left;}
  .ch-act.off{background:var(--page); color:var(--ink400); border:1px solid var(--line); cursor:default;}

  .ch-progress{display:flex; align-items:center; gap:16px; margin-bottom:20px;}
  .ch-progress .track{flex:1; height:8px; background:var(--line); border-radius:4px; overflow:hidden;}
  .ch-progress .fill{height:100%; background:var(--g700); border-radius:4px;}
  .ch-progress .lbl{font-size:calc(12.5px * var(--font-scale)); color:var(--ink600);
                    white-space:nowrap; font-weight:600;}

  @media (max-width:1100px){ .ch-grid{grid-template-columns:repeat(2,1fr);} }
  @media (max-width:680px){ .ch-grid{grid-template-columns:1fr;} }

  /* ---- scan capture tile (scan.php) ----
     The inline <svg> here carries no .icon class, so without these rules
     it falls back to fill:black at intrinsic size and renders as a giant
     black block. Size and stroke are set explicitly. */
  .wrap-center{max-width:520px; margin:0 auto; width:100%;}
  .heading{text-align:center; margin-bottom:24px;}
  .heading h1{font-size:calc(22px * var(--font-scale)); font-weight:700;
              color:var(--g950); margin-bottom:6px; line-height:1.25;}
  .heading p{font-size:calc(13px * var(--font-scale)); color:var(--ink600); line-height:1.5;}
  .scan-btn{display:flex; flex-direction:column; align-items:center; justify-content:center;
            gap:14px; width:100%; max-width:420px; margin:0 auto; padding:44px 20px;
            background:var(--g50); border:2px dashed var(--g400); border-radius:16px;
            color:var(--g700); cursor:pointer;
            transition:background .15s ease, border-color .15s ease;}
  .scan-btn:hover{background:var(--g100); border-color:var(--g700);}
  .scan-btn svg{width:64px; height:64px; flex-shrink:0;
                fill:none; stroke:var(--g700); stroke-width:1.6;
                stroke-linecap:round; stroke-linejoin:round;}
  .scan-btn .label{font-size:calc(14px * var(--font-scale)); font-weight:700; color:var(--g800);}
  #cardInput{display:none;}
  .scan-btn + .hint, .hint{font-size:calc(12px * var(--font-scale)); color:var(--ink400);
                           text-align:center; margin-top:14px;}

  .section-title{font-size:calc(11px * var(--font-scale)); font-weight:700; letter-spacing:.05em;
                 text-transform:uppercase; color:var(--ink400); margin:4px 0 10px;
                 display:flex; justify-content:space-between; align-items:center;}
  .section-title .count{color:var(--g600);}

  .index-row{display:flex; align-items:center; gap:12px; padding:11px 12px; background:var(--card);
             border:1px solid var(--line); border-radius:12px; margin-bottom:8px;}
  .index-row:hover{border-color:var(--g400);}
  .index-meta{flex:1; min-width:0;}
  /* Weight down, contrast up. At 600 the names read as a wall of bold in a
     long list; separation comes from the colour step between name and
     subtitle instead, which stays legible without shouting. */
  .index-meta .name{font-size:calc(13px * var(--font-scale)); font-weight:500;
                    color:var(--ink900);
                    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .index-meta .met{font-size:calc(10.5px * var(--font-scale)); color:var(--ink600);
                   white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  /* Plain coloured text, not a chip. In a long list a row of pills reads
     as a row of buttons and competes with the actual action button beside
     it; colour alone carries the level just as well. */
  .index-tag{font-size:calc(11.5px * var(--font-scale)); font-weight:400;
             white-space:nowrap; flex-shrink:0; padding:0; border:none;
             background:none; border-radius:0;}
  .index-tag.high{color:var(--int-high);}
  .index-tag.warm{color:var(--int-warm);}
  .index-tag.new{color:var(--int-new);}

  /* Pipeline stage in list rows. Colour tracks meaning rather than
     position: the two terminal states are green and red, and everything
     still in play is blue, deepening as it progresses. */
  .stage-tag{font-size:calc(11.5px * var(--font-scale)); font-weight:400;
             white-space:nowrap; flex-shrink:0;}
  .stage-tag.new{color:var(--ink400);}
  .stage-tag.contacted{color:var(--g600);}
  .stage-tag.qualified{color:var(--g800);}
  .stage-tag.converted{color:var(--ok-text);}
  .stage-tag.lost{color:var(--int-high);}

  /* Deal card: the one thing on the connection page a salesperson opens
     it for, sitting among identical white cards. A tinted fill plus an
     accent rail on the leading edge lifts it out without borrowing the
     navy gradient, which belongs to the identity card above. */
  .deal-card{background:var(--g50); border-color:var(--g200);
             border-left:4px solid var(--accent); position:relative;}
  .deal-card .card-head h3{color:var(--accent);}
  .deal-card .tag{background:var(--card); color:var(--accent); border:1px solid var(--g200);}

  .card-front{background:linear-gradient(135deg,var(--g900),var(--g700)); color:#fff;
              border-radius:16px; padding:22px 20px; position:relative;}
  .stamp{display:flex; align-items:center; gap:6px; font-size:calc(9.5px * var(--font-scale));
         font-weight:600; letter-spacing:.06em; text-transform:uppercase;
         color:var(--g100); margin-bottom:10px;}
  .card-front .cname{font-size:calc(22px * var(--font-scale)); font-weight:700; margin-bottom:2px;}
  .card-front .crole{font-size:calc(12.5px * var(--font-scale)); color:var(--g100); margin-bottom:14px;}
  .contact-line{display:flex; align-items:center; gap:8px;
                font-size:calc(11.5px * var(--font-scale)); color:var(--g100); margin-bottom:6px;}

  .ledger{background:var(--card); border:1px solid var(--line); border-radius:14px; padding:2px 4px;}
  /* Rows are anchors now (tap to edit that field), so link defaults have
     to be reset or every value turns blue and underlined. */
  .ledger-row{display:flex; justify-content:space-between; gap:12px; padding:9px 12px;
              border-bottom:1px solid var(--line); align-items:baseline;
              text-decoration:none; color:inherit; position:relative;
              border-radius:8px; transition:background .12s ease;
              -webkit-tap-highlight-color:transparent;}
  .ledger-row:last-child{border-bottom:none;}
  a.ledger-row:hover{background:var(--g50);}
  a.ledger-row:active{background:var(--g100);}
  /* 500 rather than 600: with ink400 darkened the label no longer needs
     extra weight to hold its own against the value. */
  .ledger-row .k{font-size:calc(10.5px * var(--font-scale)); color:var(--ink400); font-weight:500;
                 text-transform:uppercase; letter-spacing:.03em; flex-shrink:0;}
  /* Regular weight, not 600. In a list where most rows are filled, bold
     values read as a solid block; the label/value hierarchy comes from
     the uppercase grey label and the ink900 value instead. */
  .ledger-row .v{font-size:calc(12.5px * var(--font-scale)); font-weight:400;
                 color:var(--ink900);
                 text-align:right; word-break:break-word; line-height:1.4;}
  .ledger-row .v.empty{color:var(--ink400); font-weight:400;
                       /* .empty is also the page-level empty-state block
                          (card background, border, 26px padding). Both
                          selectors match here, so those are unset
                          explicitly — otherwise every "Not set" renders
                          as a boxed card and the row triples in height. */
                       background:none; border:none; border-radius:0;
                       padding:0; text-align:right; font-size:inherit;}
  a.ledger-row:hover .v.empty{color:var(--g700);}
  .v.interest-high{color:var(--int-high);}
  .v.next-action{color:var(--g700);}

  .stat-strip{display:flex; gap:10px; margin:0 0 20px;}
  .stat{flex:1; background:var(--card); border:1px solid var(--line); border-radius:12px; padding:14px;}
  .stat .num{font-weight:700; font-size:calc(21px * var(--font-scale)); color:var(--g800);}
  .stat .lbl{font-size:calc(9.5px * var(--font-scale)); color:var(--ink400);
             text-transform:uppercase; letter-spacing:.03em; margin-top:2px;}

  /* Both filter rows sit inside one .filter-bar so they read as a single
     toolbar rather than two loose rows floating on the page background. */
  .filter-bar{background:var(--card); border:1px solid var(--line); border-radius:0;
              padding:10px 12px; margin-bottom:14px;
              display:flex; flex-direction:column; gap:8px;}
  .filter-bar .filter-row{margin-bottom:0;}
  .filter-bar .filter-row + .filter-row{padding-top:8px; border-top:1px solid var(--line);}
  .filter-row{display:flex; gap:8px; margin-bottom:14px; overflow-x:auto; flex-wrap:wrap;
              -ms-overflow-style:none; scrollbar-width:none;}
  .filter-row::-webkit-scrollbar{display:none;}
  .chip{font-size:calc(10.5px * var(--font-scale)); font-weight:600; padding:6px 12px;
        border-radius:0; border:1px solid var(--line); color:var(--ink600);
        background:var(--card); white-space:nowrap; flex-shrink:0;
        display:inline-flex; align-items:center; gap:6px;
        transition:border-color .12s, background .12s, color .12s;}
  .chip:hover{border-color:var(--g400); color:var(--g800);}
  .chip.active{background:var(--g900); color:#fff; border-color:var(--g900);}
  /* count badge inside a chip — muted pill, so the number reads as
     metadata rather than part of the label */
  .chip .n{font-size:calc(9.5px * var(--font-scale)); font-weight:700; line-height:1;
           padding:3px 6px; border-radius:0; background:var(--g50); color:var(--g800);}
  .chip.active .n{background:rgba(255,255,255,.22); color:#fff;}

  /* "Select all" pulled onto the section-title line, right-aligned */
  .select-all{display:flex; align-items:center; gap:7px; text-transform:none;
              letter-spacing:0; font-weight:600; color:var(--ink600); cursor:pointer;
              font-size:calc(11.5px * var(--font-scale));}
  .select-all input{width:15px; height:15px; margin:0; accent-color:var(--g700);}

  /* stage pills (pipeline — restored) */
  .stage-row{display:flex; gap:8px; flex-wrap:wrap;}
  .stage-btn{padding:8px 14px; border-radius:9px; font-size:calc(12.5px * var(--font-scale));
             font-weight:600; border:1px solid var(--line); background:var(--card); color:var(--ink600);}
  .stage-btn.on{background:var(--g700); color:#fff; border-color:var(--g700);}

  /* ---- forms / buttons / banners ---- */
  .field{margin-bottom:12px;}
  .field label{font-size:calc(11px * var(--font-scale)); font-weight:700; letter-spacing:.04em;
               text-transform:uppercase; color:var(--ink400); display:block; margin-bottom:5px;}
  .field input, .field select, .field textarea{
    width:100%; border:1px solid var(--line); border-radius:11px; padding:11px 12px;
    font-size:calc(14px * var(--font-scale)); background:var(--card); color:var(--ink900);}
  .field textarea{resize:vertical; min-height:76px;}
  .cta-row{display:flex; gap:10px; margin-top:16px; flex-wrap:wrap;}
  .btn{flex:1; min-width:120px; display:flex; align-items:center; justify-content:center; gap:7px;
       padding:12px; border-radius:12px; font-size:calc(12.5px * var(--font-scale)); font-weight:700;
       border:1px solid var(--line); background:var(--card); color:var(--ink900);
       /* Without this a two-word label like "Compare team" breaks after
          every word — and at narrow widths, after every letter. */
       white-space:nowrap;}
  .btn.primary{background:var(--g900); color:#fff; border-color:var(--g900);}
  /* Deep-teal action button. Its own variant rather than an override on
     .btn.primary, so the navy primary stays available for everything
     outside the sales pages. */
  .btn.accent{background:var(--accent); color:#fff; border-color:var(--accent);}
  .btn.accent:hover{background:var(--accent-dark); border-color:var(--accent-dark); color:#fff;}
  .btn.accent .icon{stroke:#fff;}
  .btn.auto{flex:0 0 auto;}
  .btn:disabled{opacity:.5;}
  .btn.wa{background:var(--wa); color:#fff; border-color:var(--wa);}
  .btn.wa:hover{background:var(--wa-dark); border-color:var(--wa-dark);}

  /* labelled quick-actions for list rows */
  .qa{display:flex; gap:8px; flex-shrink:0;}
  .qa a{display:inline-flex; align-items:center; gap:6px; height:34px; padding:0 12px;
        border-radius:9px; border:1px solid var(--line); background:var(--card);
        color:var(--ink600); font-size:calc(11.5px * var(--font-scale)); font-weight:700;
        white-space:nowrap;}
  .qa a.wa{background:var(--wa); border-color:var(--wa); color:#fff;}
  .qa a.wa:hover{background:var(--wa-dark); border-color:var(--wa-dark);}
  .qa a.em{background:var(--g700); border-color:var(--g700); color:#fff;}
  .qa a.em:hover{background:var(--g800); border-color:var(--g800);}
  .qa a.locked{opacity:.5;}
  /* Below ~640px the labels would push the row into a wrap, so the
     buttons collapse back to icon-only — the colour still identifies them. */
  @media (max-width:640px){
    .qa a{padding:0 9px; height:32px;}
    .qa a .qa-label{display:none;}
  }

  /* inline WhatsApp chip next to a phone number */
  .wa-inline{display:inline-flex; align-items:center; gap:5px; padding:3px 9px;
             border-radius:20px; background:var(--wa); color:#fff;
             font-size:calc(10.5px * var(--font-scale)); font-weight:700; margin-left:8px;}
  .wa-inline:hover{background:var(--wa-dark);}
  .wa-on-brand{background:rgba(255,255,255,.18); color:#fff;}
  .wa-on-brand:hover{background:rgba(255,255,255,.28);}
  .banner{display:flex; gap:8px; align-items:flex-start; background:var(--amber-bg);
          border:1px solid var(--amber-border); color:var(--amber-text);
          font-size:calc(12.5px * var(--font-scale)); padding:10px 14px;
          border-radius:11px; margin-bottom:14px;}
  .banner.ok{background:var(--g50); border-color:var(--g200); color:var(--g800);}
  .banner.err{background:var(--error-bg); border-color:var(--error-border); color:var(--error-text);}
  .empty{background:var(--card); border:1px solid var(--line); border-radius:12px;
         padding:26px 18px; text-align:center; color:var(--ink400);
         font-size:calc(12.5px * var(--font-scale));}

  .fab{position:absolute; bottom:calc(var(--bottomnav-h) + 16px + env(safe-area-inset-bottom));
       right:18px; width:52px; height:52px; border-radius:50%; background:var(--g900); color:#fff;
       display:flex; align-items:center; justify-content:center;
       box-shadow:0 10px 22px -6px rgba(28,72,95,0.55); z-index:30;}

  /* height must ADD the safe-area inset, not absorb it: box-sizing is
     border-box globally, so `height:56px` + `padding-bottom:34px` on a
     home-indicator phone leaves only ~22px of usable space for content
     needing ~32px — the icons overflow and the bar looks detached. */
  .bottomnav{flex-shrink:0; height:var(--bottomnav-h);
             padding-bottom:env(safe-area-inset-bottom); box-sizing:content-box;
             background:var(--card); border-top:2px solid var(--g600);
             box-shadow:0 -8px 20px -8px rgba(28,72,95,.22);
             display:flex; align-items:center; justify-content:space-around; z-index:25;
             position:relative;}
  .navitem{display:flex; flex-direction:column; align-items:center; gap:4px;
           font-size:calc(10px * var(--font-scale)); color:var(--ink600); flex:1;
           padding:6px 0;
           /* Kills the ~300ms click delay and the grey flash overlay, so the
              tap state below is the only feedback the user sees. */
           touch-action:manipulation; -webkit-tap-highlight-color:transparent;
           transition:color .12s ease;}
  .navitem .icon{width:21px; height:21px; stroke-width:2; transition:transform .12s ease;}
  .navitem.active{color:var(--g700); font-weight:700;}
  /* Applied on tap, before navigation. The server round trip can take a
     second on mobile; without this the tab looks like it did nothing. */
  .navitem:active .icon, .navitem.tapped .icon{transform:scale(.88);}
  .navitem.tapped{color:var(--g700);}

  /* Thin progress bar across the top while the next page loads. Purely
     indeterminate — it can't know real progress, but it proves the tap
     registered, which is the whole point. */
  #navbar-progress{position:fixed; top:0; left:0; height:3px; width:0;
                   background:var(--g600); z-index:120; opacity:0;
                   transition:width .25s ease, opacity .2s ease;
                   pointer-events:none;}
  #navbar-progress.go{opacity:1; width:82%; transition:width 1.6s cubic-bezier(.15,.8,.35,1), opacity .2s;}
  #navbar-progress.done{width:100%; opacity:0; transition:width .15s ease, opacity .3s ease .1s;}

  .rail a{touch-action:manipulation; -webkit-tap-highlight-color:transparent;}
  .rail a .icon{transition:transform .12s ease;}
  .rail a:active .icon, .rail a.tapped .icon{transform:scale(.88);}

  .drawer-backdrop{position:fixed; inset:0; background:rgba(32,30,29,.4); z-index:40; display:none;}
  .drawer-backdrop.open{display:block;}
  .drawer{position:fixed; right:0; top:0; bottom:0; width:min(300px,82vw); background:var(--card);
          z-index:41; transform:translateX(100%); transition:transform .22s ease;
          padding:20px 18px; overflow-y:auto;}
  .drawer.open{transform:translateX(0);}
  .drawer h3{font-size:calc(12px * var(--font-scale)); text-transform:uppercase;
             letter-spacing:.06em; color:var(--ink400); margin:18px 0 8px;}
  .drawer a{display:flex; align-items:center; gap:11px; padding:11px 8px;
            font-size:calc(13.5px * var(--font-scale)); font-weight:600; border-radius:9px;}
  .drawer a:hover{background:var(--g50);}
  .drawer a.danger{color:var(--error-text);}
  .drawer .who{display:flex; align-items:center; gap:11px; padding-bottom:14px; border-bottom:1px solid var(--line);}
  .drawer .who .nm{font-size:calc(13.5px * var(--font-scale)); font-weight:700; word-break:break-all;}
  .drawer .who .em{font-size:calc(11px * var(--font-scale)); color:var(--ink400);}

  a:focus-visible, button:focus-visible{outline:2px solid var(--g600); outline-offset:2px; border-radius:8px;}

  /* ================= BREAKPOINTS ================= */
  @media (max-width:1100px){ .grid{grid-template-columns:repeat(2,1fr);} }
  @media (min-width:900px){
    .rail{display:flex;}
    .bottomnav{display:none;}
    .fab{display:none;}
    .scroll-body{padding-bottom:28px;}
    .method-grid{grid-template-columns:repeat(4,1fr);}
    .topbar{padding:16px 24px;}
  }
  @media (max-width:680px){
    .grid, .grid.g3, .grid.g2{grid-template-columns:1fr;}
    .card.wide, .card.full{grid-column:span 1;}
    .scroll-body{padding:16px 16px 24px;}
    .stat-strip{gap:8px;}
    .page-head h1{font-size:calc(18px * var(--font-scale));}

    /* .btn's 120px floor overflows narrow cards — two buttons plus a
       gap needs ~250px, more than a 320px screen leaves after padding.
       Let buttons shrink to fit instead. */
    .btn{min-width:0; padding:12px 10px;}
    .cta-row{gap:8px;}

    /* input + button rows stack rather than squeezing the input to nothing */
    .stack-sm{flex-direction:column !important; align-items:stretch !important;}
    .stack-sm .btn{width:100%;}

    .card{padding:14px;}
    .card-front{padding:18px 16px;}
    .ledger-row{padding:8px 10px;}
    .ledger-row .v{font-size:calc(12px * var(--font-scale));}
  }
  @media (prefers-reduced-motion: reduce){
    *{animation-duration:.001ms !important; transition-duration:.001ms !important;}
  }
