/* ============================================================================
   BGIS PRISM — CONSOLE SHELL
   ----------------------------------------------------------------------------
   The new navigation chrome. Loaded always, active only under:

       <html data-ui="console">

   Set from Settings > Appearance, persisted per browser as bgis_ui. Without
   the attribute this file styles nothing at all and the classic shell is
   untouched — that is the safety property the whole thing rests on.

   This is CHROME ONLY. Every one of the 44 view sections, every loader and
   every access gate is the classic app's, unchanged. What changes is the
   navigation around them:

     - 11 flat rail items + a horizontal subtab strip up to 10 wide
       becomes 6 groups + a vertical pane that can carry subheadings.
     - The contract/building filter stops being two selects below the nav
       and becomes the scope context above it.
     - Centred 720px modals become right-hand sheets.
     - View switching is instant (the classic shell fades for 350ms).
   ========================================================================== */

:root[data-ui="console"]{
  --c-rail:74px; --c-pane:238px;
  --c-line:var(--line);
  --c-r:6px;
}

/* ── swap the shells ───────────────────────────────────────────────────── */
:root[data-ui="console"] .shell{grid-template-columns:var(--c-rail) var(--c-pane) 1fr}
/* AUTO-HIDE. The pane leaves the layout entirely - the grid gives its column
   to the content - and comes back floating over it while the rail is hovered.
   Kept in CSS rather than JS: a hover panel driven by mouseenter/mouseleave
   gets stuck open the moment one event is missed, and this cannot. */
/* TWO columns, not three-with-a-zero. Making the pane position:fixed takes it
   out of the grid, so only the rail and the content remain as items - and a
   three-column template put the content in the 0px middle column and gave it
   no width at all. */
:root[data-ui="console"] .shell[data-pane="auto"]{grid-template-columns:var(--c-rail) 1fr}
:root[data-ui="console"] .shell[data-pane="auto"] .c-pane{
  position:fixed;left:var(--c-rail);top:0;bottom:0;width:var(--c-pane);z-index:80;
  transform:translateX(calc(-100% - 8px));
  transition:transform .18s var(--ease);
  box-shadow:16px 0 40px -22px rgba(0,0,0,.65)}
:root[data-ui="console"] .shell[data-pane="auto"] .c-rail:hover ~ .c-pane,
:root[data-ui="console"] .shell[data-pane="auto"] .c-pane:hover,
:root[data-ui="console"] .shell[data-pane="auto"] .c-pane:focus-within,
:root[data-ui="console"] .shell[data-pane="auto"].c-hold .c-pane{transform:none}
/* The rail hints that there is more behind it. */
:root[data-ui="console"] .shell[data-pane="auto"] .c-rail{
  box-shadow:inset -2px 0 0 -1px var(--line-2)}

/* The handle. Hidden while pinned, because there is nothing to reveal. */
.c-peek{display:none}
:root[data-ui="console"] .shell[data-pane="auto"] .c-peek{
  display:grid;place-items:center;position:absolute;right:-9px;top:50%;
  transform:translateY(-50%);width:18px;height:44px;z-index:81;
  border:1px solid var(--line-2);border-left:none;border-radius:0 7px 7px 0;
  background:var(--panel-2);color:var(--ink-mute);cursor:pointer;
  transition:background .13s,color .13s,transform .18s var(--ease)}
:root[data-ui="console"] .shell[data-pane="auto"] .c-peek svg{width:12px;height:12px}
:root[data-ui="console"] .shell[data-pane="auto"] .c-peek:hover{
  background:var(--brand);color:var(--on-brand);border-color:var(--brand)}
/* While the menu is out, the handle would sit under it - move it along. */
:root[data-ui="console"] .shell[data-pane="auto"] .c-rail:hover .c-peek,
:root[data-ui="console"] .shell[data-pane="auto"].c-hold .c-peek{opacity:0;pointer-events:none}
@media (prefers-reduced-motion:reduce){
  :root[data-ui="console"] .shell[data-pane="auto"] .c-pane{transition:none}
}
/* The button reads the state: solid divider when pinned, dashed when not.
   The button lives inside .main inside .shell, so a plain descendant selector
   reaches it - it is not a sibling of the pane. */
.c-pane-tgl .ic-unpin{display:none}
.shell[data-pane="auto"] .c-pane-tgl .ic-pin{display:none}
.shell[data-pane="auto"] .c-pane-tgl .ic-unpin{display:block}
/* Pinned is the "on" state, so it carries the accent. */
:root[data-ui="console"] .c-pane-tgl[aria-pressed="true"]{color:var(--brand)}
:root[data-ui="console"] .rail{display:none}            /* classic rail off */
:root[data-ui="console"] .subtabs{display:none!important}/* classic subtabs off */
:root:not([data-ui="console"]) .c-rail,
:root:not([data-ui="console"]) .c-pane{display:none}

/* The classic shell fades every view for 350ms. That single line is the
   loudest "not premium" tell in the product — a third of a second of fade on
   every click reads as slow however fast the data is. */
:root[data-ui="console"] .view{animation:none}
:root[data-ui="console"] .canvas{padding:20px 24px 60px;max-width:none}
:root[data-ui="console"] body{letter-spacing:-.009em}

/* ── 1. primary rail: six groups ───────────────────────────────────────── */
/* z-index is load-bearing, not decoration. The auto-hidden pane is parked at
   left:-172 with z-index:80, so its right 66px lies over the rail's 74. With
   the rail unstacked, that painted the pane's edge ON TOP of the icons - the
   rail simply vanished - and because position:sticky creates a stacking
   context, the peek handle inside it was buried too, which is why the way back
   was invisible as well. The rail sits above the parked pane. */
.c-rail{background:var(--bg);border-right:1px solid var(--c-line);position:sticky;top:0;z-index:90;
  height:100vh;display:flex;flex-direction:column;align-items:center;padding:13px 0 10px;gap:3px;
  overflow-y:auto;scrollbar-width:none}
.c-rail::-webkit-scrollbar{display:none}
.c-rail .c-mark{margin-bottom:14px;flex:none;display:block;line-height:0;
  opacity:.95;transition:opacity .13s}
.c-rail .c-mark:hover{opacity:1}
.c-rail .c-mark img{height:26px;width:auto;display:block}
.c-g{width:58px;padding:9px 2px 7px;border-radius:8px;display:flex;flex-direction:column;
  align-items:center;gap:5px;background:none;border:none;color:var(--ink-mute);cursor:pointer;
  font-family:var(--f-ui);transition:background .12s,color .12s}
.c-g svg{width:19px;height:19px;stroke-width:1.75;flex:none}
.c-g span{font-size:9.5px;font-weight:500;line-height:1;text-align:center}
.c-g:hover{color:var(--ink-dim);background:var(--panel)}
.c-g.on{color:var(--ink);background:var(--panel-2)}
.c-g.on svg{color:var(--brand)}
.c-rail .c-sp{margin-top:auto}
.c-av{width:30px;height:30px;border-radius:50%;background:linear-gradient(135deg,var(--brand),var(--navy));
  display:grid;place-items:center;font-size:11px;font-weight:700;color:#fff;cursor:pointer;
  border:none;font-family:var(--f-disp)}

/* ── 2. contextual pane ────────────────────────────────────────────────── */
.c-pane{background:var(--panel);border-right:1px solid var(--c-line);position:sticky;top:0;
  height:100vh;display:flex;flex-direction:column;overflow:hidden}
/* (the old always-collapsed mode is gone; auto-hide replaces it) */

/* the scope switcher — contract/building as context, not as a filter */
.c-scope{padding:11px 12px;border-bottom:1px solid var(--c-line);flex:none}
.c-scope-btn{width:100%;display:flex;align-items:center;gap:9px;padding:8px 9px;border-radius:var(--c-r);
  border:1px solid var(--line-2);background:var(--bg);color:var(--ink);text-align:left;cursor:pointer;
  font-family:var(--f-ui);transition:border-color .12s}
.c-scope-btn:hover{border-color:var(--brand)}
.c-scope-btn.scoped{border-color:var(--brand);background:rgba(85,156,222,.07)}
.c-scope-btn .sq{width:26px;height:26px;border-radius:6px;flex:none;display:grid;place-items:center;
  font-size:10px;font-weight:700;color:var(--on-brand);background:var(--brand);font-family:var(--f-disp)}
.c-scope-btn .tx{min-width:0;flex:1}
.c-scope-btn .tx b{display:block;font-size:12.5px;font-weight:600;line-height:1.25;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.c-scope-btn .tx em{display:block;font-style:normal;font-size:10.5px;color:var(--ink-mute);
  line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.c-scope-btn .cv{width:13px;height:13px;color:var(--ink-mute);flex:none}

.c-pane-h{padding:14px 16px 7px;font-size:14px;font-weight:600;letter-spacing:-.015em;flex:none;
  font-family:var(--f-ui)}
.c-pane-b{flex:1;overflow-y:auto;padding:0 8px 14px;scrollbar-width:thin}
.c-head{padding:12px 8px 5px;font-family:var(--f-mono);font-size:9.5px;font-weight:500;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-mute)}
.c-item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 9px;border-radius:var(--c-r);
  border:none;background:none;color:var(--ink-dim);font-family:var(--f-ui);font-size:12.75px;
  font-weight:450;text-align:left;cursor:pointer;transition:background .1s,color .1s}
.c-item:hover{background:var(--panel-2);color:var(--ink)}
.c-item.on{background:rgba(85,156,222,.13);color:var(--ink);font-weight:600}
.c-item .cnt{margin-left:auto;font-family:var(--f-mono);font-size:10px;color:var(--ink-mute)}
.c-item.on .cnt{color:var(--brand)}

/* ── 3. topbar: breadcrumb states the scope ────────────────────────────── */
:root[data-ui="console"] .topbar{padding:0 20px;height:49px;gap:10px}
:root[data-ui="console"] .topbar h2,
:root[data-ui="console"] .topbar .crumb{display:none}   /* replaced by c-crumb */
.c-crumb{display:none;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-mute);min-width:0;
  font-family:var(--f-ui);overflow:hidden;white-space:nowrap}
:root[data-ui="console"] .c-crumb{display:flex}
.c-crumb b{color:var(--ink);font-weight:600}
.c-crumb .sl{color:var(--line-2)}
.c-crumb .sc{color:var(--brand)}
.c-pane-tgl{display:none}
:root[data-ui="console"] .c-pane-tgl{display:grid}

/* ── 4. scope menu ─────────────────────────────────────────────────────── */
.c-menu{position:fixed;z-index:150;width:266px;max-height:70vh;overflow-y:auto;
  background:var(--panel);border:1px solid var(--line-2);border-radius:10px;
  box-shadow:0 24px 60px -18px rgba(0,0,0,.6);padding:6px;display:none}
.c-menu.on{display:block}
.c-menu .h{padding:8px 9px 4px;font-family:var(--f-mono);font-size:9.5px;font-weight:500;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-mute)}
.c-menu .h.div{margin-top:4px;border-top:1px solid var(--line);padding-top:9px}
.c-opt{display:flex;align-items:center;gap:9px;width:100%;padding:7px 9px;border-radius:var(--c-r);
  border:none;background:none;font-family:var(--f-ui);font-size:12.75px;color:var(--ink-dim);
  text-align:left;cursor:pointer}
.c-opt:hover{background:var(--panel-2);color:var(--ink)}
.c-opt.on{color:var(--ink);font-weight:600}
.c-opt .tick{margin-left:auto;width:14px;height:14px;color:var(--brand);flex:none}

/* ── 5. modals become right-hand sheets ────────────────────────────────────
   CSS only — no modal markup or JS is touched. The record keeps its place on
   screen instead of covering the list it came from. Making the list stay
   interactive behind it is per-modal work, and is not done here. */
:root[data-ui="console"] .modal-overlay{padding:0;align-items:stretch;justify-content:flex-end}
:root[data-ui="console"] .modal-overlay.open{display:flex}
:root[data-ui="console"] .modal{width:620px!important;max-width:94vw;max-height:100vh;
  border-radius:0;border:none;border-left:1px solid var(--line);margin:0;
  display:flex;flex-direction:column;
  animation:c-slide .26s cubic-bezier(.32,.72,0,1) both;
  box-shadow:-24px 0 60px -18px rgba(0,0,0,.55)}
:root[data-ui="console"] .modal.wide{width:820px!important}
:root[data-ui="console"] .modal-body{overflow-y:auto;flex:1}
@keyframes c-slide{from{transform:translateX(24px);opacity:.4}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){
  :root[data-ui="console"] .modal{animation:none}
}

/* ── 6. the Appearance picker (Settings) ───────────────────────────────────
   Two cards of equal weight, saying the same kinds of things in the same
   order, so the choice can be read across rather than down. The first version
   put the keyboard shortcuts inside the Console card's prose, which wrapped
   the chips onto their own lines and made that card taller and denser than
   the one it was being compared with. They live below both cards now. */
.ui-lead{margin:6px 0 0;font-size:13px;color:var(--ink-dim);line-height:1.55;max-width:60ch}
.ui-pick{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin:16px 0 0;align-items:stretch}
.ui-card{position:relative;display:flex;flex-direction:column;text-align:left;padding:16px;
  border-radius:var(--r-lg);cursor:pointer;border:1px solid var(--line-2);background:var(--bg);
  color:var(--ink);font-family:var(--f-ui);transition:border-color .13s,background .13s}
.ui-card:hover{border-color:var(--brand)}
.ui-card.on{border-color:var(--brand);background:rgba(85,156,222,.07)}
.ui-card b{display:block;font-size:15px;font-weight:600;margin-bottom:2px}
.ui-card em{display:block;font-style:normal;font-size:12.5px;color:var(--brand);
  font-weight:500;margin-bottom:10px}
.ui-card ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px}
.ui-card li{position:relative;padding-left:15px;font-size:12.5px;color:var(--ink-dim);line-height:1.45}
.ui-card li::before{content:"";position:absolute;left:3px;top:7px;width:4px;height:4px;
  border-radius:50%;background:var(--line-2)}
.ui-card.on li::before{background:var(--brand)}
/* "In use" instead of a bare tick: it names the state rather than decorating it. */
.ui-now{position:absolute;top:13px;right:13px;display:none;padding:2px 8px;border-radius:99px;
  background:var(--brand);color:var(--on-brand);font-family:var(--f-ui);font-size:10.5px;
  font-weight:600;letter-spacing:.01em}
.ui-card.on .ui-now{display:block}

/* A wireframe that shows the actual difference: one column against a column,
   a menu and a scope block. */
.ui-wire{display:flex;gap:3px;height:62px;margin-bottom:13px;border:1px solid var(--line);
  border-radius:6px;overflow:hidden;background:var(--panel);padding:3px}
.ui-wire i{display:block;border-radius:2px}
.ui-wire .w-rail{width:22px;flex:none;background:var(--line-2)}
.ui-wire .w-rail-n{width:12px;flex:none;background:var(--brand);opacity:.6}
.ui-wire .w-pane{width:24px;flex:none;background:var(--line);display:flex;
  flex-direction:column;gap:2px;padding:2px}
.ui-wire .w-scope{height:8px;flex:none;background:var(--brand);opacity:.75;border-radius:2px}
.ui-wire .w-list{flex:1;background:repeating-linear-gradient(var(--line-2) 0 2px,transparent 2px 5px)}
.ui-wire .w-body{flex:1;background:var(--bg);display:flex;flex-direction:column;gap:3px;padding:2px}
.ui-wire .w-tabs{height:5px;flex:none;background:var(--line-2);border-radius:2px}
.ui-wire .w-fill{flex:1;background:repeating-linear-gradient(var(--line) 0 3px,transparent 3px 8px)}

/* Shortcuts, out of the cards and on one line each. */
.ui-keys{display:flex;flex-wrap:wrap;align-items:center;gap:8px 18px;margin:16px 0 0;
  padding:11px 13px;border:1px solid var(--line);border-radius:var(--r);background:var(--panel);
  font-size:12.5px;color:var(--ink-dim)}
.ui-keys-lab{font-family:var(--f-mono);font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-mute)}
.ui-keys kbd{display:inline-block;min-width:19px;padding:2px 5px;margin:0 2px;text-align:center;
  border:1px solid var(--line-2);border-bottom-width:2px;border-radius:4px;background:var(--bg);
  font-family:var(--f-mono);font-size:10.5px;color:var(--ink);line-height:1.35}
.ui-foot{margin:14px 0 0;font-size:12.5px;color:var(--ink-mute);line-height:1.55;max-width:64ch}

/* Tablet: the pane keeps its column but gives up some width. */
@media (max-width:1080px){
  :root[data-ui="console"]{--c-pane:210px}
  .ui-pick{grid-template-columns:1fr}
}

/* ── MOBILE ────────────────────────────────────────────────────────────────
   Both columns become one off-canvas drawer, matching what the classic rail
   already does at this width. Both, not just the rail: six group icons with no
   menu behind them reach only the first item of each group, which is 6 of the
   44 destinations. The scope switcher lives in the pane too, so a rail-only
   drawer would also strand contract and building.

   The desktop auto-hide is deliberately overridden here - "appears on hover"
   means nothing on a touch screen, and its transform would fight the drawer. */
@media (max-width:860px){
  /* Size through the variables the desktop rules already read, rather than
     restating left/width at a weaker specificity. `:root[data-ui] .c-pane` is
     (0,2,0) and the auto-hide rule is `:root[data-ui] .shell[data-pane] .c-pane`
     at (0,4,0), so the desktop geometry was winning on a phone: the pane sat at
     left:74 with width:210 (the tablet --c-pane), which put its right edge at
     +74 - on screen, over the content. Measured on the device, not guessed. */
  :root[data-ui="console"]{
    --c-rail:64px;
    --c-pane:min(238px, calc(100vw - 64px - 44px))}

  :root[data-ui="console"] .shell,
  :root[data-ui="console"] .shell[data-pane="auto"]{grid-template-columns:1fr}

  :root[data-ui="console"] .c-rail,
  :root[data-ui="console"] .shell[data-pane="auto"] .c-pane,
  :root[data-ui="console"] .shell .c-pane{
    position:fixed;top:0;bottom:0;z-index:60;
    transition:transform .2s var(--ease);
    box-shadow:none}
  :root[data-ui="console"] .c-rail{
    left:0;width:var(--c-rail);transform:translateX(-100%)}

  /* (0,4,0) and (0,3,0), after the auto-hide rule, so these win.
     The shift is the pane's width PLUS the rail's: translateX(-100%) alone
     moves it by its own width only, which lands its right edge exactly on the
     rail's and leaves it covering the first 64px of the page. */
  :root[data-ui="console"] .shell[data-pane="auto"] .c-pane,
  :root[data-ui="console"] .shell .c-pane{
    left:var(--c-rail);width:var(--c-pane);display:flex;
    transform:translateX(calc(-100% - var(--c-rail)));
    box-shadow:16px 0 44px -20px rgba(0,0,0,.6)}

  /* Open: both slide in together and the scrim covers the rest. */
  :root[data-ui="console"] .shell.c-drawer .c-rail,
  :root[data-ui="console"] .shell.c-drawer .c-pane,
  :root[data-ui="console"] .shell.c-drawer[data-pane="auto"] .c-pane{transform:none}
  :root[data-ui="console"] .shell.c-drawer .rail-scrim{
    display:block;position:fixed;inset:0;z-index:55;background:rgba(0,0,0,.5);
    -webkit-tap-highlight-color:transparent}

  /* The hamburger is the classic one; console.js points it at the drawer. */
  :root[data-ui="console"] .menu-btn{display:flex!important}
  /* Pinning is a desktop idea. */
  :root[data-ui="console"] .c-pane-tgl{display:none}

  :root[data-ui="console"] .topbar{flex-wrap:wrap;height:auto;padding:10px 13px;gap:9px}
  :root[data-ui="console"] .c-crumb{order:3;flex-basis:100%;font-size:11.5px}
  :root[data-ui="console"] .canvas{padding:15px 12px 72px}
  :root[data-ui="console"] .c-g{width:52px;padding:8px 2px 6px}
  :root[data-ui="console"] .c-g span{font-size:8.5px}
  :root[data-ui="console"] .c-rail .c-mark img{height:22px}

  /* Touch targets: 6px of padding is a desktop number. */
  :root[data-ui="console"] .c-item{padding:10px 10px;font-size:13.5px}
  :root[data-ui="console"] .c-opt{padding:10px 9px}

  /* A side sheet on a phone is just a screen. Take the whole width. */
  :root[data-ui="console"] .modal,
  :root[data-ui="console"] .modal.wide{width:100%!important;max-width:100%;border-left:none}
  /* The scope menu is anchored to a button inside the drawer, so keep it
     above the drawer rather than behind it. */
  .c-menu{z-index:70}
}

/* ── 7. the invite ────────────────────────────────────────────────────────
   Sits in the topbar's empty middle — the gap between the page title and the
   live badge, which `.live{margin-left:auto}` has always left blank. Using it
   means the invite costs no vertical space and nothing reflows when it goes.

   Not styled under [data-ui="console"]: this is shown to people who are still
   on the classic shell, so it has to work there. console.js decides when. */
.ui-invite{display:flex;align-items:center;gap:9px;margin-left:18px;padding:5px 6px 5px 11px;
  border:1px solid rgba(85,156,222,.42);background:rgba(85,156,222,.10);border-radius:99px;
  font-family:var(--f-ui);min-width:0;max-width:430px;flex:0 1 auto}
/* The invite must give way before anything else in the topbar does: the title
   block keeps its line, and the invite's sentence truncates instead. */
.topbar.has-invite .crumb,
.topbar.has-invite h2{white-space:nowrap}
.ui-inv-ic{width:15px;height:15px;flex:none;color:var(--brand)}
.ui-inv-tx{font-size:12.5px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-inv-go{flex:none;padding:4px 11px;border-radius:99px;border:none;cursor:pointer;
  background:var(--brand);color:var(--on-brand);font-family:var(--f-ui);font-size:12px;font-weight:600;
  transition:background .13s}
.ui-inv-go:hover{background:var(--brand-hover)}
.ui-inv-x{flex:none;width:22px;height:22px;border-radius:50%;border:none;background:none;cursor:pointer;
  color:var(--ink-mute);display:grid;place-items:center;transition:.13s}
.ui-inv-x:hover{color:var(--ink);background:rgba(255,255,255,.08)}
.ui-inv-x svg{width:13px;height:13px}

/* Below ~1180px the topbar's middle is no longer dead space — the title, the
   weather badge and the action buttons want it. Drop the sentence first, then
   the whole invite, rather than letting it squeeze the controls. */
@media (max-width:1180px){ .ui-inv-tx{display:none} }
@media (max-width:900px){ .ui-invite{display:none!important} }

/* Shown when a contract is chosen but nothing in the loaded data maps buildings
   to it, so the list below is the whole estate rather than that contract's. */
.c-note{padding:7px 10px;margin:2px 2px 4px;border-radius:var(--c-r);
  background:rgba(240,169,44,.10);border:1px solid rgba(240,169,44,.30);
  font-family:var(--f-ui);font-size:11px;line-height:1.45;color:var(--ink-dim)}
/* The affirmative variant: CAFM supplied a real, contract-accurate estate. */
.c-note.ok{background:rgba(61,220,151,.10);border-color:rgba(61,220,151,.30)}

/* A contract nested under its parent. The "+N" says the parent selection
   covers N more contracts, so picking Savills reading as "Savills and King's
   Cross" is visible rather than a surprise. */
.c-opt.c-sub{padding-left:26px;position:relative}
.c-opt.c-sub::before{content:"";position:absolute;left:15px;top:50%;width:6px;height:1px;
  background:var(--line-2)}
.c-kids{margin-left:auto;font-family:var(--f-mono);font-size:10px;color:var(--ink-mute);
  padding:1px 5px;border:1px solid var(--line-2);border-radius:4px}
.c-opt.on .c-kids{color:var(--brand);border-color:var(--brand)}

/* One-time note when the menu is put away, so it does not just disappear. */
.c-hint{position:fixed;left:50%;bottom:26px;transform:translate(-50%,14px);z-index:200;
  padding:10px 16px;border-radius:99px;border:1px solid var(--line-2);background:var(--panel-2);
  color:var(--ink);font-family:var(--f-ui);font-size:12.5px;box-shadow:0 18px 44px -20px rgba(0,0,0,.7);
  opacity:0;pointer-events:none;transition:opacity .2s var(--ease),transform .2s var(--ease)}
.c-hint.on{opacity:1;transform:translate(-50%,0)}
