/* ==========================================================================
   loco-ui — CLIENT PORTAL LAYER
   Loads AFTER loco-ui.css, which IS this portal's shared design system.

   WHY THIS FILE EXISTS (14 Aug 2026). Until now the portal carried its own
   inline <style> copy of the whole system while loco-ui.css carried another,
   and the two had already drifted: the portal had 47 selectors loco-ui lacked
   (the email log and the rich-reply editor, both added 13 Aug). Spinning up a
   SECOND client portal would have made that a three-way drift, which is why
   the skill says to migrate before the second instance, not after.

   The split was provably safe: of 347 shared selectors, 347 had byte-identical
   bodies. Only two rules differed, and both were the deliberate edits recorded
   in the skill — `.app` (auth gating, restored below) and `:root` (loco-ui adds
   `--muted`, naming the #9aa6ae the portal hardcodes).

   RULE: a SHARED component changes in loco-ui.css and every surface gets it.
   Anything only a client portal has — auth gating, the ticket editor, the
   email log — belongs here.
   ========================================================================== */

/* ---------- auth gating -----------------------------------------------------
   loco-ui.css ships `.app{display:flex}` because the HQ, chat and hub have no
   login wall. The portal does: the app stays hidden until `body.authed`, or the
   client's workspace would flash on screen before the session is checked.    */
.app{display:none}
body.authed .app{display:flex}
body.authed .login{display:none}

body.authed .app{display:flex}
body.authed .login{display:none}
.md-bar{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin-bottom:6px}
.md-tool{font-family:var(--font-b);font-size:12px;font-weight:600;color:var(--slate);
    background:#fff;border:1px solid var(--line);border-radius:8px;padding:5px 9px;cursor:pointer;
    line-height:1;transition:.12s}
.md-tool:hover{border-color:var(--copper4);color:var(--copper6)}
.md-tool.active{background:var(--copper1);border-color:transparent;color:var(--copper6)}
.md-tool b,.md-tool i{font-size:12.5px}
.md-sep{width:1px;height:18px;background:var(--line);margin:0 3px}
.md-right{margin-left:auto}
.cmt-form textarea.drop{border-color:var(--copper4);box-shadow:0 0 0 3px var(--copper1);
    background:var(--copper1)}
.md-preview{display:none;margin-top:8px;padding:12px 14px;border:1px dashed var(--line);
    border-radius:10px;background:var(--paper)}
.md-preview.on{display:block}
.md-hint{font-family:var(--font-m);font-size:10px;letter-spacing:.04em;color:#9aa6ae;margin-top:6px}
.md-body img.md-img{display:block;max-width:100%;height:auto;margin:10px 0;border-radius:10px;
    border:1px solid var(--line)}
.cmt-b .bx.md-body{font-size:13.5px}
.cmt-b .bx.md-body p{margin:0 0 8px}
.cmt-b .bx.md-body .md-ul,.cmt-b .bx.md-body .md-ol{margin:4px 0 8px}
.admin-only{display:none}
body[data-role="admin"] .admin-only{display:flex}
.badge.sent{color:var(--green);background:var(--green-bg)}
.badge.failed{color:var(--red);background:var(--red-bg)}
.ml-chart{display:flex;align-items:flex-end;gap:3px;height:92px;margin-top:4px}
.ml-day{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:flex-end;gap:2px;height:100%;border-radius:4px;padding-bottom:1px}
.ml-day:hover{background:var(--line2)}
.ml-seg{border-radius:3px;min-height:3px}
.ml-seg.s{background:var(--copper4)}
.ml-seg.f{background:var(--red)}
.ml-zero{height:3px;background:var(--line);border-radius:3px}
.ml-axis{display:flex;justify-content:space-between;font-family:var(--font-m);font-size:10px;color:#9aa6ae;margin-top:9px}
.ml-key{display:flex;gap:16px;align-items:center;font-size:12px;color:var(--slate)}
.ml-key i{width:9px;height:9px;border-radius:3px;display:inline-block;margin-right:6px;vertical-align:-1px}
.ml-tools{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-bottom:16px}
.ml-search{flex:1;min-width:180px;max-width:320px;border:1px solid var(--line);background:#fff;border-radius:9px;padding:9px 13px;font-size:13.5px;font-family:var(--font-b);color:var(--ink)}
.ml-search:focus{outline:none;border-color:var(--copper4)}
.ml-tr{cursor:pointer}
.ml-tr:hover{background:var(--paper)}
.ml-tr.on{background:var(--paper)}
.ml-to{font-weight:600}
.ml-to small{display:block;color:var(--slate);font-weight:400;font-size:12px}
.ml-when{font-family:var(--font-m);font-size:12px;color:var(--slate);white-space:nowrap}
.ml-det>td{background:var(--paper);padding:0 14px 20px}
.ml-err{background:var(--red-bg);color:var(--red);border-radius:var(--r-sm);padding:12px 14px;font-family:var(--font-m);font-size:11.5px;line-height:1.55;white-space:pre-wrap;word-break:break-word}
.ml-meta{display:flex;flex-wrap:wrap;gap:8px 22px;font-size:12.5px;color:var(--slate);margin:14px 0 12px}
.ml-meta b{color:var(--ink);font-weight:600}
.ml-prev{width:100%;height:440px;border:1px solid var(--line);border-radius:var(--r-sm);background:#fff;display:block}
.ml-nobody{background:var(--blue-bg);color:var(--blue);border-radius:var(--r-sm);padding:12px 14px;font-size:13px;line-height:1.55}
@media(max-width:700px){.ml-hide-s{display:none}.ml-prev{height:320px}}

/* ---------- overview callout ----------------------------------------------
   The single thing waiting on the client, shown above the project cards.
   Copper rather than amber: this is a prompt, not a warning, and amber is
   already spoken for by overdue billing. Renders nothing when CLIENT.callout
   is absent, which is the default. */
.callout{display:flex;gap:16px;align-items:flex-start;background:var(--copper1);
  border:1px solid var(--copper4);border-radius:var(--r);padding:20px 22px;margin-bottom:24px}
.callout .co-ic{flex:none;width:34px;height:34px;border-radius:9px;display:grid;place-items:center;
  background:var(--white);border:1px solid var(--copper4);color:var(--copper)}
.callout .co-ic svg{width:17px;height:17px}
.callout .co-b{min-width:0}
.callout .co-k{font-family:var(--font-m);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--copper6);margin:0 0 5px}
.callout h3{font-family:var(--font-d);font-size:16px;font-weight:600;margin:0 0 6px;color:var(--ink)}
.callout .co-b>p:last-of-type{font-size:13.5px;line-height:1.6;color:var(--slate);margin:0}
.callout .co-a{margin-top:14px}
@media(max-width:640px){.callout{padding:16px 16px;gap:12px}}

/* A short plain-English line under a project's title. Carries the status of work
   that has no stepper to describe it (proposed, paused, awaiting a decision). */
.proj-note{font-size:13.5px;line-height:1.6;color:var(--slate);margin:14px 0 0}

/* Caption on the admin-only "Our time" field. Amber-tinted so it reads as an
   internal marker, and it says in words that the client never sees the figure. */
.internal-note{font-size:11.5px;color:var(--amber);font-style:italic}

/* "View as client" preview pill — unmistakable while an admin is seeing the client view.
   Floats bottom-centre so nothing shifts; ink ground so it can't be mistaken for client UI. */
.viewasbar{position:fixed;bottom:18px;left:50%;transform:translateX(-50%);z-index:80;
  display:flex;align-items:center;gap:10px;background:var(--ink);color:#fff;
  border-radius:24px;padding:9px 12px 9px 16px;box-shadow:var(--sh-lg,0 12px 32px rgba(10,20,30,.28));
  font-size:13px;white-space:nowrap;max-width:calc(100vw - 32px)}
.viewasbar svg{width:16px;height:16px;flex:none;opacity:.8}
.viewasbar span{overflow:hidden;text-overflow:ellipsis}
.viewasbar button{border:0;cursor:pointer;background:var(--copper);color:#fff;font:inherit;
  font-size:12.5px;font-weight:600;border-radius:16px;padding:6px 13px;flex:none}
.viewasbar button:hover{filter:brightness(1.08)}

/* Admin-only strip on the Feedback page: shows the Loco-controlled current review
   round and the button that advances it. New feedback joins the current round
   rather than each submission spinning up its own. */
.round-strip{display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  background:var(--copper1);border:1px solid var(--copper4);border-radius:var(--r);
  padding:12px 18px;margin-bottom:20px}
.round-strip .rs-txt{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;min-width:0}
.round-strip .rk{font-family:var(--font-m);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--copper6)}
.round-strip b{font-family:var(--font-d);font-size:15px;font-weight:600;color:var(--ink)}
.round-strip .rk-note{font-size:12.5px;color:var(--slate)}
.round-strip>button{margin-left:auto;flex:none}

/* Status filter chips on the Support & Feedback lists (Open / Resolved / All / Archived).
   Default view is live work; finished tickets stay in the system (and visible to the client)
   one click away. Active chip is solid ink; the count sits in a small inset pill. */
.tfilter{display:inline-flex;gap:6px;flex-wrap:wrap}
.tfilter button{display:inline-flex;align-items:center;gap:7px;font-family:var(--font-b);
  font-size:13px;font-weight:500;color:var(--slate);background:#fff;border:1px solid var(--line);
  border-radius:20px;padding:6px 13px;cursor:pointer;transition:.12s;line-height:1}
.tfilter button:hover{border-color:var(--copper4);color:var(--copper6)}
.tfilter button.on{background:var(--ink);border-color:var(--ink);color:#fff}
.tfilter button.arch.on{background:var(--slate);border-color:var(--slate)}
.tfilter button i{font-style:normal;font-family:var(--font-m);font-size:10.5px;font-weight:600;
  background:var(--paper);color:var(--slate);border-radius:10px;padding:1px 6px;min-width:15px;text-align:center}
.tfilter button.on i{background:rgba(255,255,255,.22);color:#fff}

/* ---------- projects grid & card polish (26 Aug 2026) --------------------- */
/* Two staged cards side by side crush below ~1240px (the ui.css grids only
   collapse at 1000) - stack the PROJECTS grid early. */
@media(max-width:1240px){.grid.proj-grid{grid-template-columns:1fr}}
/* Pin card CTAs to the bottom so equal-height grid rows finish together. */
.card.proj{display:flex;flex-direction:column}
.card.proj .proj-foot{margin-top:auto;padding-top:18px}
.card.live-proj{display:flex;flex-direction:column}
.card.live-proj .proj-foot{margin-top:auto;padding-top:18px}
/* Overview stat cards: bottom-anchor the footer links across the row. */
.card.mini{display:flex;flex-direction:column;align-items:flex-start}
.card.mini .link-more{margin-top:auto;padding-top:12px}
/* Money column reads right-aligned. */
.tbl th.amt,.tbl td.amt{text-align:right}
/* Count badge on the selected (dark) filter chip was too dim. */
.tfilter button.on i{background:rgba(255,255,255,.32)}

/* ---------- mobile navigation (26 Aug 2026) -------------------------------- */
/* ui.css hides the sidebar below 1000px with no replacement - the burger in the
   topbar toggles it back in as a drawer. go() closes it on every navigation. */
.nav-burger{display:none}
.nav-scrim{display:none}
@media(max-width:1000px){
  .nav-burger{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;
    width:38px;height:38px;border:1px solid var(--line);border-radius:10px;background:#fff;
    color:var(--ink);cursor:pointer;padding:0}
  .topbar{padding:0 16px;gap:12px}
  body.nav-open .sidebar{display:flex;position:fixed;top:0;left:0;bottom:0;height:100vh;
    width:min(78vw,300px);z-index:120;box-shadow:0 10px 40px rgba(16,24,32,.25)}
  body.nav-open .nav-scrim{display:block;position:fixed;inset:0;background:rgba(16,24,32,.35);z-index:110}
}

/* ==========================================================================
   ACCESSIBILITY LAYER (7 Sep 2026, Loco HQ cutover) - SPEC "Client portal".
   Nothing above this line changed: the live 178-line file is byte-identical
   so a tenant's cutover has zero visual change. Everything below only shows
   itself to keyboard and screen-reader users, or on an error state.
   ========================================================================== */

/* Visually hidden, still read out (the 2FA code input's label). */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* Visible focus for keyboard users only (:focus-visible), copper ring on every interactive
   element - loco-ui.css removes the outline on inputs and the search box, so the ring is
   re-added here for the keyboard case without touching the mouse look. */
:where(a,button,input,select,textarea,[role="button"],[tabindex]:not([tabindex="-1"])):focus-visible{
  outline:3px solid var(--copper4,#E0A98E);outline-offset:2px;border-radius:6px}
.tk-head:focus-visible,.noti:focus-visible,.qrow:focus-visible,.doc-row:focus-visible,.att:focus-visible{
  outline:3px solid var(--copper4,#E0A98E);outline-offset:-3px}
.nav-item:focus-visible{outline:3px solid var(--copper4,#E0A98E);outline-offset:-3px}
.btn:focus-visible,.md-tool:focus-visible,.tfilter button:focus-visible{outline:3px solid var(--copper4,#E0A98E);outline-offset:2px}

/* Modal validation / save errors (role=alert), hidden until there is something to say. */
.modal-err{display:none;margin-top:12px;padding:10px 12px;border-radius:9px;font-size:13px;line-height:1.5;
  background:var(--red-bg,#FBEAEA);color:var(--red,#B3261E)}
.modal-err.on{display:block}

/* The reset-password page reuses the login card; its "done" state is a plain message. */
.auth-msg{font-size:13.5px;line-height:1.6;color:var(--slate);margin:6px 0 16px}

/* ---------- narrow phones (10 Sep 2026, measured in a browser at 390 and 360) ----------
   Topbar: the right-hand cluster plus the "Client view" pill ran 12-42px past the screen edge at 390,
   so the sign-out button was off-screen on Overview, Feedback, Support and Documents. Below 560 the
   pill is dropped and a long title ellipses instead of pushing the cluster out.
   Ticket rows: the ref and the status column left the title column 41-62px wide and its chips spilled
   out of it; the row now wraps, so the status sits under the title.
   Billing: the five-column table scrolled sideways inside its card (525px in 348); each invoice
   becomes a stacked row - number and status, description and amount, then the dates. */
@media(max-width:560px){
  .topbar .role-pill{display:none}
  .topbar .tt{min-width:0;overflow:hidden;text-overflow:ellipsis}
  /* Ticket rows (11 Sep): ref, status and chevron share the top line and the title gets the full width
     under them - the wrapping flex row left the ref floating alone beside a 222px title column. A
     feedback round's "2/5 done" takes its own line under the meta, so the chevron never wraps alone. */
  .tk-head{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;
    grid-template-areas:"ref . status chev" "main main main main";column-gap:12px;row-gap:8px;align-items:center}
  .tk-ref{grid-area:ref;white-space:nowrap}
  .tk-main{grid-area:main}
  .tk-right{display:contents}
  .tk-right .badge{grid-area:status}
  .tk-right .chev{grid-area:chev}
  .tk-right .tk-count{grid-column:1/-1;white-space:nowrap}
  /* List bar (11 Sep): the chips keep one line (scrolling sideways if an admin's Archived chip does not
     fit) and the create button takes the full width under them on one line. The padding and negative
     margin leave room for the 5px focus ring inside the scroll box. */
  .bar-row{flex-wrap:wrap;gap:12px}
  .bar-row .tfilter{flex:1 1 100%;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;padding:5px;margin:-5px}
  .bar-row .tfilter::-webkit-scrollbar{display:none}
  .tfilter button{flex:0 0 auto}
  .bar-row .btn{flex:1 1 100%;margin-left:0;white-space:nowrap}
  #view-billing .tbl thead{display:none}
  #view-billing .tbl,#view-billing .tbl tbody{display:block}
  #view-billing .tbl tr{display:grid;grid-template-columns:minmax(0,1fr) auto;
    grid-template-areas:"num st" "desc amt" "dates dates";gap:6px 14px;padding:14px 6px;border-bottom:1px solid var(--line2)}
  #view-billing .tbl tr:last-child{border-bottom:none}
  #view-billing .tbl td{padding:0;border:0;min-width:0}
  #view-billing .tbl td:nth-child(1){grid-area:num}
  #view-billing .tbl td:nth-child(2){grid-area:desc}
  #view-billing .tbl td:nth-child(3){grid-area:amt}
  #view-billing .tbl td:nth-child(4){grid-area:dates;font-size:13px}
  #view-billing .tbl td:nth-child(4):empty{display:none}
  #view-billing .tbl td:nth-child(5){grid-area:st;justify-self:end}
}

/* ---------- polish: portal-page (11 Sep 2026) ----------------------------------
   Rules for the markup the portal-page polish pass changed in index.html. */
/* Page heads now carry just the h1 (the eyebrow and the stock intros went), so it sits at the top. */
.page-head>h1:first-child{margin-top:0}
/* Overview "Support & billing" row: with fewer than three cards (no care plan, a hidden view) they share
   two columns rather than leaving a hole. More specific than loco-ui's collapse, so it collapses itself. */
.grid.g-3.n2{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(max-width:1000px){.grid.g-3.n2{grid-template-columns:1fr}}
/* Billing summary: one strip in place of two mostly-empty hero cards, so the invoices sit above the fold. */
.bill-sum{display:flex;flex-wrap:wrap;gap:8px 32px;padding:12px 0;margin-bottom:24px;border-top:1px solid var(--line2);border-bottom:1px solid var(--line2)}
.bill-sum .bs{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;min-width:0}
.bill-sum .bs-k{font-family:var(--font-m);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.bill-sum .bs-v{font-family:var(--font-d);font-weight:600;font-size:17px;color:var(--ink)}
.bill-sum .bs-v.out{color:var(--amber)}
.bill-sum .bs-x{font-size:12.5px;color:var(--slate)}
/* Sign-in: no orphaned last word, and the remember / forgot pair stays on one line each. */
.login-card .sub,.login-foot{text-wrap:balance}
.lg-row{gap:12px}
.lg-row a,.lg-row .check{white-space:nowrap}
/* ...but at 320 the pair (226px + gap) no longer fits the 194px card interior, so let the row
   wrap instead of letting "Forgot password?" hang outside the card. No effect at 390+, where it fits. */
@media(max-width:560px){.lg-row{flex-wrap:wrap;row-gap:8px}}

/* ==========================================================================
   POLISH (11 Sep 2026). The first 178 lines must stay a byte-identical copy of the live
   public/portal-layer.css (test/state.test.mjs), so these override rules above rather
   than editing them in place.
   ========================================================================== */

/* Callouts: the copper ground was written for the one overview prompt (the callout with a .co-ic),
   but it was unscoped, so the static "Prefer email?" hint and the feedback advice read as loud action
   boxes. Every other callout goes back to loco-ui's quiet white callout. */
.callout:not(:has(>.co-ic)){background:linear-gradient(180deg,#fff,#fffdfb);border-color:var(--copper1)}
.callout:not(:has(>.co-ic)) h3{font-size:15.5px;margin:0}

/* Project cards: margin-top:auto pins the footer down but resolves to 0 when the card is not stretched,
   so the divider sat right under the last line. Keep 24px above it, and let a lone live card fill the
   height of the staged card beside it. */
.card.proj>:has(+.proj-foot),.card.live-proj>:has(+.proj-foot){margin-bottom:24px}
.proj-grid>div>.card.live-proj:only-child{flex:1}

/* Closed shared loco-ui's blue pill with New. Closed is finished work, so it goes quiet grey. */
.badge.closed{color:var(--slate);background:var(--line2)}

/* Composer: Post comment (no border) and Attach file (ghost, 1px border) drew 31px and 33px tall. */
.cmt-actions .btn{height:34px;padding-block:0}
/* The reply box grows with the text (mdGrow in index.html) up to about half the screen, then scrolls. */
.cmt-form textarea{max-height:50vh}

/* Thread bubbles: Loco's replies were the same grey as the client's. Loco's go white with a hairline;
   internal notes keep their amber. */
.cmt.admin:not(.internal) .bx{background:#fff;border:1px solid var(--line)}

/* Touch targets (WK-5): 44px on touch screens and narrow windows - the same OR-ed query as
   platform-layer.css. Filter chips, small buttons, attachment chips, "more" links and the bell
   panel's two buttons were 16-33px tall. */
@media(hover:none),(max-width:700px){
  .tfilter button,.btn-sm,.att,.link-more{min-height:44px}
  .md-tool{min-height:40px;min-width:40px}
  /* ...and ONE row of them, as HQ does: at 40px all ten tools wrapped to two rows (84px), taller than the box.
     Heading, numbered list, checklist and code go; typed markdown still renders. */
  .md-tool[data-md=h],.md-tool[data-md=ol],.md-tool[data-md=task],.md-tool[data-md=code]{display:none}
  .noti-h{padding-top:6px;padding-bottom:6px}
  .noti-h button{min-height:44px;padding:0 4px}
}

/* View-as pill on a phone (14 Sep 2026): the "Open portal" banner says who, that it is read only, that a Loco
   admin is looking and when it ends - about 60 characters, which a single nowrap line cut off at "L..." on a
   390px screen. The pill now sizes to its text up to the screen edge and WRAPS instead of truncating, so every
   word is readable at any width; on a wide screen it is still one line. */
.viewasbar{width:max-content;white-space:normal}
.viewasbar span{min-width:0;overflow:visible;text-overflow:clip;line-height:1.35}
