/* Keyda Business dashboard.
   ONE product, one look: these tokens, the type scale and the component
   shapes are taken from business-site/site.css so the marketing site, the
   docs and the app a customer signs into are visibly the same thing. If you
   change a colour or a radius here, change it there too.
   Dark mode is the owner's choice, not the OS's alone: `data-theme` on <html>
   wins in BOTH directions so an explicit Light stays light on a dark machine,
   and "System" (no attribute) follows prefers-color-scheme. Every colour is
   defined on bare :root first — a token whose ONLY definition lived inside a
   media query would be undefined for half the users. */
:root{
  /* Page is the site's tinted section colour; cards are its white. */
  --bg:#f7f8fc; --surface:#ffffff; --surface-2:#f1f3f9; --line:#e6e9f2;
  --ink:#101425; --ink-2:#3d4560; --ink-3:#727b96;
  --brand:#3b4ee0; --brand-ink:#fff; --brand-soft:#eef0ff;
  --ok:#0d9b6c; --ok-soft:#e3f7ef; --warn:#b8760b; --warn-soft:#fdf3e0;
  --bad:#d33b4d; --bad-soft:#fdeaec;
  --topbar:rgba(255,255,255,.86);
  --field:#f7f8fc;
  --r:12px; --r-lg:18px;
  --sh:0 1px 2px rgba(16,20,37,.05), 0 12px 34px -18px rgba(16,20,37,.28);
  color-scheme:light;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --bg:#0b0e1a; --surface:#141a2e; --surface-2:#1c2340; --line:#29304f;
    --ink:#eef1fa; --ink-2:#aab3ce; --ink-3:#7d88a6;
    --brand:#8b98ff; --brand-ink:#0b0e1a; --brand-soft:#242c50;
    --ok:#35c795; --ok-soft:#11301f; --warn:#e0a53a; --warn-soft:#332612;
    --bad:#ff7183; --bad-soft:#3a1720;
    --topbar:rgba(20,26,46,.86);
    --field:#0f1424;
    --sh:0 1px 2px rgba(0,0,0,.34), 0 14px 36px -20px rgba(0,0,0,.7);
    color-scheme:dark;
  }
}
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#0b0e1a; --surface:#141a2e; --surface-2:#1c2340; --line:#29304f;
  --ink:#eef1fa; --ink-2:#aab3ce; --ink-3:#7d88a6;
  --brand:#8b98ff; --brand-ink:#0b0e1a; --brand-soft:#242c50;
  --ok:#35c795; --ok-soft:#11301f; --warn:#e0a53a; --warn-soft:#332612;
  --bad:#ff7183; --bad-soft:#3a1720;
  --topbar:rgba(20,26,46,.86);
  --field:#0f1424;
  --sh:0 1px 2px rgba(0,0,0,.34), 0 14px 36px -20px rgba(0,0,0,.7);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{background:var(--bg);color:var(--ink);font:15px/1.6 Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;-webkit-font-smoothing:antialiased}
a{color:var(--brand);text-decoration:none}
h1,h2,h3{margin:0;line-height:1.18;letter-spacing:-.02em;font-weight:700}
h1{font-size:23px}h2{font-size:17px}h3{font-size:14px}
p{margin:0}
.muted{color:var(--ink-2)}.dim{color:var(--ink-3)}.small{font-size:13px}.tiny{font-size:12px}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px}
.boot{display:grid;place-items:center;height:100vh}
/* ── layout ─────────────────────────────────────────────────────────── */
.shell{display:grid;grid-template-columns:248px 1fr;grid-template-rows:auto 1fr;min-height:100vh}
/* Same translucent, blurred bar the marketing site uses for its nav. */
.topbar{grid-column:1/-1;display:flex;align-items:center;gap:12px;padding:12px 20px;background:var(--topbar);backdrop-filter:blur(10px);border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20}
.brand{display:flex;align-items:center;gap:9px;font-weight:800;letter-spacing:-.02em}
.brand .dot{width:26px;height:26px;border-radius:8px;background:var(--brand);display:grid;place-items:center;color:#fff;font-size:14px;font-weight:800}
.brand small{font-weight:500;color:var(--ink-3);font-size:12px;padding-left:6px;border-left:1px solid var(--line)}
.spacer{flex:1}
.sidebar{background:var(--surface);border-right:1px solid var(--line);padding:14px 10px;display:flex;flex-direction:column;gap:18px}
.navgroup>.label{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-3);padding:0 8px 7px}
.navitem{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:var(--r);color:var(--ink-2);font-weight:500;cursor:pointer;border:none;background:none;width:100%;text-align:left;font-size:14px;font-family:inherit}
.navitem:hover{background:var(--surface-2);color:var(--ink)}
.navitem.on{background:var(--brand-soft);color:var(--brand);font-weight:600}
.navitem .ic{width:18px;text-align:center;font-size:14px}
.navitem .badge{margin-left:auto;background:var(--bad);color:#fff;border-radius:999px;font-size:11px;font-weight:700;padding:1px 6px}
.navitem.soon{opacity:.5;cursor:default}
.main{padding:26px 32px 64px;max-width:1240px;width:100%;margin:0 auto}
.head{display:flex;align-items:flex-start;gap:14px;margin-bottom:18px;flex-wrap:wrap}
.head .grow{flex:1;min-width:220px}
.head .sub{color:var(--ink-2);font-size:14px;margin-top:3px}
/* ── components ─────────────────────────────────────────────────────── */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh);padding:16px}
.card+.card{margin-top:16px}
.card .ttl{display:flex;align-items:center;gap:8px;margin-bottom:4px}
.card .desc{color:var(--ink-2);font-size:13px;margin-bottom:12px}
.grid{display:grid;gap:14px}
.grid.c2{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.grid.c4{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px}
.stat .n{font-size:26px;font-weight:700;letter-spacing:-.02em}
.stat .k{font-size:12px;color:var(--ink-3);text-transform:uppercase;letter-spacing:.05em;font-weight:600}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:9px 14px;border-radius:var(--r);border:1px solid var(--line);background:var(--surface);color:var(--ink);font:inherit;font-size:14px;font-weight:550;cursor:pointer;transition:.12s}
.btn:hover{background:var(--surface-2)}
.btn:disabled{opacity:.5;cursor:not-allowed}
.btn.pri{background:var(--brand);border-color:var(--brand);color:var(--brand-ink)}
.btn.pri:hover{filter:brightness(1.08)}
.btn.danger{color:var(--bad);border-color:var(--bad)}
.btn.danger:hover{background:var(--bad-soft)}
.btn.sm{padding:6px 10px;font-size:13px}
.btn.link{border:none;background:none;color:var(--brand);padding:4px 6px}
.row{display:flex;gap:9px;align-items:center;flex-wrap:wrap}
label.f{display:block;margin-bottom:12px}
label.f>span{display:block;font-size:13px;font-weight:600;margin-bottom:5px}
label.f>span em{font-weight:400;color:var(--ink-3);font-style:normal}
input,textarea,select{width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:var(--r);background:var(--field);color:var(--ink);font:inherit;font-size:14px;transition:border-color .12s,box-shadow .12s}
input:focus,textarea:focus,select:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
textarea{min-height:78px;resize:vertical}
.pill{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:999px;font-size:12px;font-weight:650}
.pill.ok{background:var(--ok-soft);color:var(--ok)}
.pill.warn{background:var(--warn-soft);color:var(--warn)}
.pill.bad{background:var(--bad-soft);color:var(--bad)}
.pill.neutral{background:var(--surface-2);color:var(--ink-2)}
.list{border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.item{display:flex;gap:11px;align-items:center;padding:11px 13px;border-bottom:1px solid var(--line);background:var(--surface)}
.item:last-child{border-bottom:none}
.item .grow{flex:1;min-width:0}
.item .t{font-weight:550;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.empty{padding:26px;text-align:center;color:var(--ink-3);font-size:14px}
.code{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r);padding:12px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px;overflow-x:auto;white-space:pre;color:var(--ink)}
.check{display:flex;gap:11px;align-items:flex-start;padding:10px 0;border-bottom:1px dashed var(--line)}
.check:last-child{border:none}
.check .box{width:20px;height:20px;border-radius:6px;display:grid;place-items:center;font-size:12px;font-weight:800;flex:0 0 auto}
.check .box.y{background:var(--ok);color:#fff}
.check .box.n{background:var(--surface-2);color:var(--ink-3);border:1px solid var(--line)}
.spinner{width:16px;height:16px;border:2px solid var(--line);border-top-color:var(--brand);border-radius:50%;animation:sp .7s linear infinite}
.spinner.lg{width:30px;height:30px;border-width:3px}
@keyframes sp{to{transform:rotate(360deg)}}
.toasts{position:fixed;right:16px;bottom:16px;display:flex;flex-direction:column;gap:8px;z-index:100}
.toast{background:var(--ink);color:var(--bg);padding:11px 14px;border-radius:var(--r);box-shadow:var(--sh);font-size:14px;max-width:380px;animation:in .18s}
.toast.err{background:var(--bad);color:#fff}
.toast.ok{background:var(--ok);color:#fff}
@keyframes in{from{opacity:0;transform:translateY(6px)}}
/* auth */
.auth{min-height:100vh;display:grid;place-items:center;padding:20px}
.auth .box{width:100%;max-width:392px}
.auth .card{padding:26px}
/* The mark on the sign-in card. Slightly larger than the sidebar's — this is
   the first screen anyone sees and there is room for it. */
.authbrand{margin-bottom:18px}
.authbrand .brand{font-size:19px}
.authbrand .brand .logo{width:34px;height:34px}
.authbrand .brand .dot{width:32px;height:32px;font-size:17px}
.auth h1{margin-bottom:6px}
.hr{display:flex;align-items:center;gap:10px;color:var(--ink-3);font-size:12px;margin:16px 0}
.hr:before,.hr:after{content:"";flex:1;height:1px;background:var(--line)}
/* chat */
.chat{display:flex;flex-direction:column;gap:10px;max-height:52vh;overflow-y:auto;padding:4px}
.msg{max-width:78%;padding:9px 12px;border-radius:14px;font-size:14px;white-space:pre-wrap;word-break:break-word}
.msg.u{align-self:flex-end;background:var(--brand);color:var(--brand-ink);border-bottom-right-radius:4px}
.msg.b{align-self:flex-start;background:var(--surface-2);border-bottom-left-radius:4px}
.msg .meta{display:block;margin-top:5px;font-size:11px;opacity:.75}
/* Rendered bot text (richText in ui.js). The bubble itself is pre-wrap for
   the owner's plainly-typed side; the rendered side turns that off because
   its paragraphs, breaks and lists are real nodes and pre-wrap would double
   every gap. */
.msg .rich{white-space:normal}
.msg .rich p,.msg .rich ul,.msg .rich ol{margin:0}
.msg .rich p+p,.msg .rich p+ul,.msg .rich p+ol,.msg .rich ul+p,.msg .rich ol+p,.msg .rich p+.hh{margin-top:7px}
.msg .rich ul,.msg .rich ol{padding-left:19px;display:flex;flex-direction:column;gap:3px}
.msg .rich strong{font-weight:650}
.msg .rich .hh{font-weight:700;font-size:14.5px}
.msg .rich a{color:var(--brand);font-weight:600;text-decoration:underline;text-underline-offset:2px;overflow-wrap:anywhere}
.msg .rich code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.88em;background:var(--surface);padding:1px 5px;border-radius:5px}
.tabs{display:flex;gap:5px;border-bottom:1px solid var(--line);margin-bottom:14px;overflow-x:auto}
.tab{padding:8px 12px;border:none;background:none;color:var(--ink-2);font:inherit;font-size:14px;font-weight:550;cursor:pointer;border-bottom:2px solid transparent}
.tab.on{color:var(--brand);border-bottom-color:var(--brand)}
.modal{position:fixed;inset:0;background:rgba(10,14,30,.55);display:grid;place-items:center;z-index:200;padding:20px}
.modal .card{max-width:440px;width:100%}
@media(max-width:820px){
  .shell{grid-template-columns:1fr}
  .sidebar{flex-direction:row;overflow-x:auto;border-right:none;border-bottom:1px solid var(--line);padding:8px}
  .navgroup{display:flex;align-items:center;gap:4px}
  .navgroup>.label{display:none}
  .main{padding:14px}
}

/* ── uploads: drop zone + visible queue ─────────────────────────────────
   The queue is the point. A bare <input type=file> shows one filename and
   silently replaces it on the next pick, so an owner adding six policies had
   no way to see what was about to be sent. */
.drop{border:1.5px dashed var(--line);border-radius:var(--r-lg);background:var(--surface-2);padding:20px;text-align:center;transition:.14s}
.drop.over{border-color:var(--brand);background:var(--brand-soft)}
.dropin{display:flex;flex-direction:column;align-items:center;gap:7px}
.dropin strong{font-size:14.5px}
.dropin .tiny{max-width:420px}
.filelist{margin-top:10px;display:flex;flex-direction:column;gap:6px}
.fileitem{display:flex;align-items:center;gap:10px;padding:8px 11px;border:1px solid var(--line);border-radius:var(--r);background:var(--surface);font-size:13.5px}
.fileitem .fname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:550}
.fileitem .x{border:none;background:none;color:var(--ink-3);cursor:pointer;font-size:14px;line-height:1;padding:2px 4px;border-radius:6px;font-family:inherit}
.fileitem .x:hover{background:var(--bad-soft);color:var(--bad)}

/* ── policies: type it / link it / upload it ────────────────────────────── */
.policies{display:flex;flex-direction:column;gap:12px}
.policy{border:1px solid var(--line);border-radius:var(--r-lg);padding:13px 14px;background:var(--surface)}
.policy .prow{display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap}
.policy label.f{margin-bottom:0}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;overflow:hidden;background:var(--surface-2)}
.segb{border:none;background:none;font:inherit;font-size:13px;font-weight:550;color:var(--ink-2);padding:6px 13px;cursor:pointer;transition:.12s}
.segb:hover{color:var(--ink)}
.segb.on{background:var(--brand);color:#fff}

/* A non-fatal disclosure on a source that worked but was only partly read. */
.warnline{color:var(--warn);margin-top:3px}

/* A drafted answer awaiting approval — visibly not yet live. */
.item.draft{border-left:3px solid var(--brand);background:var(--surface)}

/* Keep inputs on a grid row aligned even when one label's hint wraps to a
   second line — otherwise a longer hint shunts its field half a row down and
   the form reads as broken. */
.grid.c2,.grid.c4{align-items:stretch}
.grid label.f{display:flex;flex-direction:column;height:100%;margin-bottom:0}
.grid label.f>input,.grid label.f>textarea,.grid label.f>select{margin-top:auto}

/* ── brand mark + theme toggle ──────────────────────────────────────────── */
.brand .logo{width:28px;height:28px;border-radius:8px;object-fit:contain;display:block}
.btn.icon{width:34px;padding:0;font-size:15px;line-height:1;flex:0 0 auto}
@media(max-width:1100px){.hide-sm{display:none}}

/* ── polish ─────────────────────────────────────────────────────────────
   Wider gutters, a clearer heading rhythm and more generous cards. The old
   values were tuned for a 1080px column; at full width the screen read as a
   narrow strip of dense boxes pushed against the sidebar. */
.head{margin-bottom:22px}
.head h1{font-size:25px}
.card{padding:20px 22px}
.card+.card{margin-top:16px}
.card .ttl{margin-bottom:6px}
.card .ttl h2{font-size:17.5px}
.card .desc{font-size:13.5px;margin-bottom:14px;max-width:78ch}
.grid{gap:16px}
.stat{padding:16px 18px;transition:border-color .14s}
.stat:hover{border-color:var(--brand)}
.stat .n{font-size:28px;line-height:1.1}
.stat .k{margin-top:4px}
.empty{padding:34px 26px;line-height:1.5}
.list{border-radius:var(--r-lg)}
.item{padding:13px 15px}
.item:hover{background:var(--surface-2)}
.tabs{gap:2px;margin-bottom:18px}
.tab{padding:9px 14px;font-size:14.5px}
.btn{border-radius:10px}
.pill{padding:3px 10px}

/* Contextual help — every screen should be able to point at the guide that
   explains it without the owner hunting through the docs hub. */
.helpline{display:flex;align-items:center;gap:6px;margin-top:10px;font-size:13px;color:var(--ink-3)}
.helpline a{font-weight:600}

@media(max-width:820px){
  .main{padding:16px 14px 48px}
  .card{padding:16px}
}

/* Line-icon buttons (the theme toggle). Sized here so the SVG never inherits
   a text font-size and lands off-centre next to real buttons. */
.btn.icon{width:36px;height:36px}
.btn.icon svg{width:17px;height:17px;display:block}

/* ── action spacing ─────────────────────────────────────────────────────
   A button that follows a field must never touch it.

   Fields inside a .grid have margin-bottom:0 (the grid's own `gap` spaces
   them, and equal heights are what keeps inputs on a row aligned). That left
   the Save button flush against the input below every such block — Business
   settings, Train, Install and anywhere else the same shape is used. Spacing
   belongs to the ACTION, not the field, so it is stated once here instead of
   as an inline style per view. */
.card > .row,
.card > .btn,
.grid + .row, .grid + .btn,
label.f + .row, label.f + .btn,
.list + .row, .list + .btn,
.drop + .row, .filelist + .row,
.code + .row, .code + .btn{margin-top:16px}
/* …but a row that is already the first thing in a card needs no gap. */
.card > .ttl + .row{margin-top:10px}

/* ── block rhythm ───────────────────────────────────────────────────────
   The previous rules only spaced things INSIDE a card. Half the layout is
   siblings AFTER one: the "Save details" button that follows the Policies
   card, the platform tabs that follow the key card, a guide card that follows
   a wrapper. Those all rendered flush against the card above them.

   Adjacent margins collapse in normal flow, so a card following .head or
   .tabs still gets one gap, not two. */
* + .card{margin-top:16px}
.card + .row, .card + .btn, .card + .tabs, .card + .grid, .card + .list{margin-top:16px}

/* A panel that only appears once you pick something from the list above it.
   :empty keeps it from reserving a gap while nothing is open. */
.detail:not(:empty){margin-top:16px}

/* A drafted answer is a little FORM (two inputs and two buttons), not a list
   row — flush rows read as one run-on block. */
.item.draft{padding:16px 15px}
.item.draft + .item.draft{border-top:1px solid var(--line)}

/* The drop zone's own button was 7px under its hint line. */
.dropin{gap:10px}

/* A field that follows a grid — the fallback/escalation boxes under the
   two-column block on Install — had no gap, because grid fields carry no
   bottom margin and the grid's own `gap` does not reach outside it. */
.grid + label.f, .grid + .f{margin-top:14px}

/* A touch more air under a field's label; 5px was tight once the control
   was something taller than an input (a row of colour swatches). */
label.f>span{margin-bottom:7px}

/* Drafted answers stack as their own small cards. They are forms — two
   inputs and two buttons each — so flush list rows read as one run-on block. */
.stack{display:flex;flex-direction:column;gap:12px}
.draft{border:1px solid var(--line);border-left:3px solid var(--brand);border-radius:var(--r);background:var(--surface);padding:14px 15px}
.ttl + .list, .desc + .list{margin-top:10px}

/* ── device preview (Test screen) ────────────────────────────────────────
   The iframe renders at TRUE device width and is scaled down with a
   transform, so the page inside lays out exactly as it would on that device.
   Scaling the frame instead would just squeeze a desktop layout and show the
   owner something no visitor will ever see. */
.stage{
  display:flex; justify-content:center; padding:22px 16px;
  background:var(--surface-2); border:1px solid var(--line);
  border-radius:var(--r-lg); overflow-x:auto;
}
.device{flex:0 0 auto;background:var(--surface);box-shadow:0 18px 46px -22px rgba(16,20,37,.5)}
.device .viewport{overflow:hidden;position:relative;background:#fff}
.device .screen{border:0;display:block;transform-origin:top left}

/* A browser window. */
.device.desktop{border:1px solid var(--line);border-radius:12px;overflow:hidden}
.device.desktop .chrome{
  display:flex; align-items:center; gap:6px; height:34px; padding:0 12px;
  background:var(--surface-2); border-bottom:1px solid var(--line);
}
.device.desktop .chrome i{width:9px;height:9px;border-radius:50%;background:var(--line)}
.device.desktop .chrome .addr{
  margin-left:10px; flex:1; background:var(--surface); border:1px solid var(--line);
  border-radius:999px; font-size:11.5px; color:var(--ink-3); padding:3px 12px;
  text-align:center; max-width:280px;
}

/* A phone. */
.device.phone{border:9px solid #12172a;border-radius:34px;padding:0;position:relative;overflow:hidden}
.device.phone .viewport{border-radius:25px}
.device.phone .notch{
  position:absolute; top:0; left:50%; transform:translateX(-50%);
  width:110px; height:20px; background:#12172a; border-radius:0 0 12px 12px; z-index:2;
}
/* While the pass is being issued and the frame mounts. Given the stage's own
   height so switching tabs does not collapse the card and jump the page. */
/* Bot link: the code and its explanation sit side by side, and stack on a
   narrow screen rather than shrinking the code — a QR below a usable size is
   not a smaller QR, it is an unscannable one. */
.linkqr{display:flex;gap:22px;align-items:flex-start;margin-top:18px;flex-wrap:wrap}
.qr{flex:0 0 auto;background:#fff;padding:12px;border:1px solid var(--line);border-radius:var(--r-lg)}
.qr canvas{display:block;image-rendering:pixelated}
.qrnote{flex:1 1 260px;min-width:240px}
.qrnote h3{font-size:14.5px;margin:0 0 6px;letter-spacing:-.01em}
/* Step headings inside an install guide. */
.sub2{font-size:13px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;color:var(--ink-3);margin:18px 0 8px}
.card .sub2:first-of-type{margin-top:14px}
/* A card that is telling the owner something is wrong, without shouting. */
.warncard{border-color:var(--warn);background:var(--warn-soft)}
.warncard .desc{color:var(--ink-2)}
.stageload{display:flex;align-items:center;justify-content:center;min-height:420px;width:100%}
.previewnote{margin-top:12px;max-width:70ch}
@media(max-width:820px){ .stage{padding:14px 10px} }

/* The bezel must sit OUTSIDE the viewport, not eat into it. With the default
   border-box the 9px phone bezel stole 18px from a 390px screen, so the chat
   page laid out at 390 and then had its right edge — including the Send
   button — clipped away. */
.device{box-sizing:content-box}
.device .viewport{box-sizing:content-box}

/* Country dial-code picker (sign-in).
   The panel opens UPWARD: the sign-in card is vertically centred, so a
   downward panel lands under the phone's on-screen keyboard exactly when the
   number field has focus. */
.cc{position:relative}
.cc-btn{display:flex;align-items:center;gap:7px;width:100%;padding:10px 10px;border:1px solid var(--line);border-radius:var(--r);background:var(--field);color:var(--ink);font:inherit;font-size:14px;cursor:pointer;transition:border-color .12s,box-shadow .12s}
.cc-btn:hover{border-color:var(--ink-3)}
.cc-btn:focus-visible{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.cc-btn[aria-expanded="true"]{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.cc-flag{font-size:16px;line-height:1}
.cc-code{font-variant-numeric:tabular-nums;font-weight:600}
.cc-caret{margin-left:auto;width:0;height:0;border:4px solid transparent;border-top-color:var(--ink-3);margin-top:3px}
.cc-pop{position:absolute;bottom:calc(100% + 6px);left:0;z-index:40;width:290px;max-width:78vw;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh);overflow:hidden}
.cc-pop.down{bottom:auto;top:calc(100% + 6px)}
.cc-pop[hidden]{display:none}
.cc-searchwrap{padding:9px;border-bottom:1px solid var(--line)}
.cc-search{font-size:14px}
.cc-list{max-height:236px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
.cc-item{display:flex;align-items:center;gap:9px;padding:9px 11px;cursor:pointer;font-size:14px;border-bottom:1px solid var(--line)}
.cc-item:last-child{border-bottom:none}
.cc-item:hover,.cc-item.on{background:var(--brand-soft)}
.cc-item .cc-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cc-item .cc-dial{color:var(--ink-3);font-variant-numeric:tabular-nums;font-size:13px}
.cc-item.cc-custom .cc-name{font-weight:650;color:var(--brand)}
.cc-empty{padding:14px 12px;color:var(--ink-3);font-size:13px;text-align:center}
@media (prefers-reduced-motion:reduce){.cc-btn{transition:none}}

/* ── comboBox: the grouped, searchable picker ──────────────────────────────
   Reuses every .cc-* rule above (same popup, same flip, same rows) and adds
   only what a full-width, grouped, label-carrying field needs. */

/* Field wrapper for a control that is NOT a native input. Same look as
   label.f, on a div: a <label> binds to its first labelable descendant, which
   for this picker is the search box inside its own popup. Values match
   label.f exactly, so the two shapes are indistinguishable on screen. */
.f{display:block;margin-bottom:12px}
.f>span{display:block;font-size:13px;font-weight:600;margin-bottom:7px}
/* Only the picker's caption is clickable. `.f>span` also matches every
   label.f>span in the app (label.f carries class `f`), and `cursor` is not
   declared there — so an unscoped pointer here would cascade onto every
   field caption in the dashboard, each promising a click that does nothing. */
.f>span.cbcap{cursor:pointer}
.f>span em{font-weight:400;color:var(--ink-3);font-style:normal}
.grid .f{display:flex;flex-direction:column;height:100%;margin-bottom:0}
/* The grid aligns fields on a row by pushing the CONTROL to the bottom. The
   existing rule names input/textarea/select; .cc is a fourth kind of control
   and without this the picker floats up while the text field beside it sits
   on the baseline. */
.grid .f>.cc{margin-top:auto}
.policy .f{margin-bottom:0}
.f + .row, .f + .btn{margin-top:16px}

/* Full width, unlike the dial-code popup's fixed 290px column. */
.cc-pop.wide{width:100%;min-width:260px}
/* The button's label is text, not a flag + code, so it needs to grow and
   ellipsise — "Freelancer / independent professional" is a real row. */
.cc-btn .cc-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}
.cc-btn .cc-name.cc-ph{color:var(--ink-3)}
/* Group headings. Sticky because the list scrolls 194 rows and a heading that
   scrolls away leaves you reading trade names with no idea which trade group
   you are in. */
.cc-group{position:sticky;top:0;z-index:1;background:var(--surface);padding:8px 11px 5px;font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-3);border-bottom:1px solid var(--line)}
/* The row that is already chosen, so re-opening the picker shows you where
   you are instead of making you re-read the list. */
.cc-item.sel .cc-name{font-weight:650;color:var(--brand)}
.cc-item.cc-clear .cc-name{color:var(--ink-3)}
