/* ============================================================================
   Travelieons design system — ported from "Travelieons CRM.dc.html" concept.
   Terracotta-orange brand on a warm cream canvas. Violet is retained ONLY as
   the AI accent, so AI surfaces stay distinct from the brand. Bootstrap 5
   augmentation, no build step. Self-hosted fonts (no CDN).
   See files/design/TRAVELIEONS_DESIGN_CONCEPT.md.
   ========================================================================== */
@import url("../fonts/fonts.css");

/* The design has arrived: show the page. layouts/tenant hides <html> until
   this sheet loads, so nobody sees the workspace as unstyled blue links. */
html { visibility: visible; }

:root {
  /* Brand */
  --ti-primary: #F26B32;
  --ti-primary-2: #FB8B3D;
  --ti-primary-deep: #241207;
  --ti-primary-deeper: #3A2416;
  --ti-primary-light: #FDBA74;
  --ti-brand-tint: #FFEEDD;
  /* Brand as raw channels, for the rgba() tints used by shadows and active states. */
  --ti-primary-rgb: 242, 107, 50;
  --ti-ink: #1a1340;              /* editorial headings + solid dark buttons */

  /* Sunset accent / money-in */
  --ti-accent: #FF7A59;
  --ti-amber: #F59E0B;
  --ti-magenta: #B14BE0;
  --ti-pink: #E11D74;

  /* AI accent — deliberately still violet so AI reads as its own thing */
  --ti-ai-a: #E0409A;
  --ti-ai-b: #8B5CF6;
  --ti-ai-c: #6D28D9;

  /* Super Admin (light indigo console) */
  --ti-admin-accent: #3538CD;
  --ti-admin-accent-2: #4F46E5;
  --ti-admin-bg: #F6FBFA;
  --ti-admin-bg-2: #EDF5F3;
  --ti-admin-surface: #FFFFFF;
  --ti-admin-border: #E5E8F6;
  --ti-admin-sidebar-border: #DFE3FF;
  --ti-admin-text: #0F172A;
  --ti-admin-subtext: #64748B;
  /* Alias: the console views were written against --ti-admin-sub, which never
     existed, so their muted text was falling back to full-strength ink. */
  --ti-admin-sub: #64748B;
  --ti-admin-cyan: #22D3EE;       /* survives only as a chart/map accent */

  /* Surfaces & text
     ---------------------------------------------------------------------
     Retuned 2026-08-14. The old set read as washed out on the cream canvas
     and nothing separated from anything: --ti-border #ECE2D5 against --ti-bg
     #F6EEE3 is roughly 5% contrast, so card edges were invisible and every
     panel ran into the next. Text sat at grey #1F2937 with secondary copy at
     #6B7280 and #9AA3B2, which on a bright background is a lot of glare for
     very little legibility.

     These are the design file's own values (Packages Module / Quotation Flow
     v3): near-black indigo for text, a warmer and darker border. Changed here
     rather than per screen so the whole product moves together — that is what
     :root is for. */
  --ti-bg: #F4EBDE;
  --ti-surface: #FFFFFF;
  --ti-border: #E4D9C9;
  --ti-muted-fill: #FAF7F2;
  --ti-soft-fill: #F5EDE2;
  --ti-hairline: #F1E9DE;         /* table row rules */
  --ti-text: #1A1340;
  --ti-subtext: #5B5470;
  --ti-faint: #8A8296;

  /* Semantic status */
  --ti-lead-new: #0EA5E9;
  --ti-lead-contacted: #6366F1;
  --ti-lead-quote: #F59E0B;
  --ti-lead-nego: #F97316;
  --ti-won: #16A34A;
  --ti-lost: #9CA3AF;
  --ti-info: #0EA5E9;
  --ti-success: #16A34A;
  --ti-warning: #D97706;
  --ti-danger: #DC2626;
  --ti-teal: #14B8A6;

  /* Gradients */
  --ti-grad-primary: linear-gradient(135deg, #F26B32, #FB8B3D);
  --ti-grad-warm: linear-gradient(135deg, #F26B32, #FDBA74);   /* logo mark, avatars, day numbers */
  --ti-grad-amber: linear-gradient(135deg, #FF7A59, #F59E0B);
  --ti-grad-sidebar: linear-gradient(180deg, #FFFFFF, #F7F0E6);
  --ti-grad-ai: linear-gradient(120deg, #E0409A, #8B5CF6 60%, #6D28D9);
  --ti-grad-hero: linear-gradient(155deg, #241207, #F26B32 42%, #B14BE0 72%, #FF7A59);
  --ti-grad-admin: linear-gradient(155deg, #312E81, #3538CD 45%, #4F46E5 78%, #818CF8);
  --ti-grad-revenue: linear-gradient(140deg, #F2542D, #F97316 46%, #FB923C 78%, #FFB27A);

  /* Radii */
  --ti-r-card: 16px;
  --ti-r-input: 11px;
  --ti-r-pill: 999px;
  --ti-r-hero: 22px;
}

/* ---- Base ---- */
body {
  margin: 0;
  font-family:var(--ti-font-body, 'Instrument Sans', system-ui, sans-serif);
  color: var(--ti-text);
  background: var(--ti-bg);
  -webkit-font-smoothing: antialiased;
}

/* `hidden` MEANS HIDDEN.
   The browser's own [hidden] rule is the weakest thing in the cascade, so any
   class that sets display beats it — .ti-btn is display:inline-flex, and a
   button switched off with el.hidden = true stayed on screen. The app sets
   .hidden from JS in several places (the packages editor, the DMC send bar);
   this makes all of them behave the way that line reads. */
[hidden] { display: none !important; }
.ti-display { font-family:var(--ti-font-display, 'Bricolage Grotesque', sans-serif); letter-spacing: -.01em; font-weight: 800; }
.ti-num { font-variant-numeric: tabular-nums; }
.ti-money { font-variant-numeric: tabular-nums; text-align: right; }
a { color: var(--ti-primary); text-decoration: none; }
a:hover { color: #D6551F; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #d8cbba; border-radius: 8px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }

/* ---- Keyframes (defined once; reuse, don't reinvent) ---- */
@keyframes fadeUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn { 0% { opacity: 0; transform: scale(.9); } 60% { transform: scale(1.02); } 100% { opacity: 1; transform: scale(1); } }
@keyframes slideRight { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: none; } }
@keyframes slideUp { from { opacity: 0; transform: translateY(60px); } to { opacity: 1; transform: none; } }
@keyframes growW { from { width: 0; } }
@keyframes growH { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes shimmer { 0% { background-position: -400px 0; } 100% { background-position: 400px 0; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(.94); } }
@keyframes sparkle { 0%, 100% { opacity: .4; transform: scale(.8); } 50% { opacity: 1; transform: scale(1.25); } }
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
@keyframes ring { 0% { box-shadow: 0 0 0 0 rgba(245,158,11,.5); } 70% { box-shadow: 0 0 0 12px rgba(245,158,11,0); } 100% { box-shadow: 0 0 0 0 rgba(245,158,11,0); } }
@keyframes toastIn { from { opacity: 0; transform: translate(-50%,24px); } to { opacity: 1; transform: translate(-50%,0); } }
@keyframes drift { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes twinkle { 0%, 100% { opacity: .15; } 50% { opacity: 1; } }
@keyframes skyShift { 0%, 100% { background-position: 0% 40%; } 50% { background-position: 100% 60%; } }
@keyframes cloud { from { transform: translateX(-180px); } to { transform: translateX(560px); } }
@keyframes cardLift { from { transform: translateY(6px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes dash { to { stroke-dashoffset: 0; } }
@keyframes flyacross { 0% { transform: translateX(0) rotate(12deg); } 100% { transform: translateX(360px) rotate(12deg); } }

.ti-anim-fadein { animation: fadeIn .3s both; }
.ti-anim-fadeup { animation: fadeUp .5s both; }
.sk { background: linear-gradient(90deg,#eef1f6 25%,#f7f9fc 37%,#eef1f6 63%); background-size: 800px 100%; animation: shimmer 1.3s infinite linear; }

/* ---- Cards ---- */
.ti-card { background: var(--ti-surface); border: 1px solid var(--ti-border); border-radius: var(--ti-r-card); padding: 18px; box-shadow: 0 1px 3px rgba(16,24,40,.04); }
.ti-card-hd { display: flex; justify-content: space-between; align-items: center; font-weight: 700; font-size: 14.5px; margin-bottom: 14px; }
.ti-card-hover { transition: transform .16s, box-shadow .16s; }
.ti-card-hover:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(var(--ti-primary-rgb), .16); }

/* ---- Buttons ---- */
.ti-btn { display: inline-flex; align-items: center; gap: 7px; border: none; border-radius: var(--ti-r-input); font-weight: 700; font-size: 13.5px; padding: 10px 16px; transition: transform .12s, box-shadow .12s; cursor: pointer; }
.ti-btn:hover { transform: translateY(-1px); }
.ti-btn-pri { background: var(--ti-grad-primary); color: #fff; box-shadow: 0 4px 14px rgba(var(--ti-primary-rgb), .28); }
.ti-btn-amber { background: var(--ti-grad-amber); color: #fff; box-shadow: 0 4px 14px rgba(245,158,11,.3); }
.ti-btn-wa { background: #25D366; color: #fff; }
.ti-btn-ghost { background: #fff; color: #374151; border: 1px solid var(--ti-border); }
.ti-btn-block { width: 100%; justify-content: center; padding: 13px; }
/* Animating background-position repaints on the main thread every frame, and this
   button is on screen in the topbar of every page — it made scrolling stutter.
   The shimmer now runs only while the pointer is on it. */
.ti-btn-ai { background: var(--ti-grad-ai); background-size: 180% 180%; color: #fff; box-shadow: 0 3px 14px rgba(224,64,154,.32); }
.ti-btn-ai:hover { animation: skyShift 5s ease infinite; }

/* ---- Working button (data-busy, see vendor/app/busy-button.js) ----
   A slow submit — reading an itinerary out of a PDF, calling a gateway — swaps
   the button's icon for this spinner and disables it, so the press is visibly
   taken and cannot be repeated. `currentColor` keeps it right on every variant,
   filled or ghost. */
.ti-spin { display: inline-block; width: 1em; height: 1em; flex: none; border-radius: 50%;
           border: 2px solid currentColor; border-top-color: transparent; opacity: .85;
           vertical-align: -.15em; animation: spin .7s linear infinite; }
.ti-busy { cursor: progress; opacity: .82; }
.ti-busy:hover { transform: none; filter: none; }
@media (prefers-reduced-motion: reduce) { .ti-spin { animation-duration: 2s; } }

/* ---- Status pills (single legend, use everywhere) ---- */
.ti-pill { display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: var(--ti-r-pill); font-size: 11px; font-weight: 700; white-space: nowrap; }
.ti-pill-lg { padding: 4px 11px; }
/* color driven by inline --c (background = tint, text = solid): style="--c:#16A34A" */
.ti-pill[style*="--c"] { background: color-mix(in srgb, var(--c) 13%, transparent); color: var(--c); }

/* ---- Fields ---- */
.ti-field { display: flex; align-items: center; gap: 10px; background: var(--ti-muted-fill); border: 1px solid var(--ti-border); border-radius: var(--ti-r-input); padding: 11px 13px; margin-bottom: 14px; transition: border-color .15s, background .15s, box-shadow .15s; }
.ti-field:hover { border-color: #CFD5E0; }
/* Without a focus state a form reads as a page of grey boxes — you cannot tell where you are typing. */
.ti-field:focus-within { background: #fff; border-color: var(--ti-primary); box-shadow: 0 0 0 3px rgba(var(--ti-primary-rgb), .13); }
.ti-field:focus-within > i { color: var(--ti-primary) !important; }

/* A field the app fills in for you (check-out from check-in + nights). Reads as
   an answer rather than an empty box you forgot: flat, no hover, no caret. */
.ti-field.is-derived { background: #F4F1EC; border-style: dashed; }
.ti-field.is-derived:hover { border-color: var(--ti-border); }
.ti-field.is-derived:focus-within { background: #F4F1EC; border-color: var(--ti-border); box-shadow: none; }
.ti-field.is-derived input { color: var(--ti-subtext); cursor: default; }
.ti-field input { border: none; background: transparent; outline: none; flex: 1; font-size: 14px; color: var(--ti-text); width: 100%; }

/* A TEXTAREA IN A .ti-field IS STILL THE FIELD.
   Only `input` was given the "fill the box, lose your own chrome" treatment
   above, so a textarea dropped into the same wrapper kept its browser default —
   a ~20-character box with its own border, sitting in the middle of a field
   three times its width, with the resize grip over the placeholder. It is the
   same control; it gets the same rule, plus a top alignment so a three-row box
   starts at the top of the field rather than floating in the middle of it. */
.ti-field textarea {
  border: none; background: transparent; outline: none; flex: 1;
  font: inherit; font-size: 14px; color: var(--ti-text);
  width: 100%; min-width: 0; resize: vertical; min-height: 60px;
}
.ti-field textarea::placeholder { color: #A8B0BF; }
.ti-field:has(textarea) { align-items: flex-start; }
/* Live inline validation (forms marked data-live-validate). */
.ti-field.ti-invalid { border-color: var(--ti-danger); background: #FEF2F2; }
.ti-field.ti-invalid:focus-within { box-shadow: 0 0 0 3px rgba(220, 38, 38, .13); }
/* The same state on a searchable dropdown (the error sits on its .ti-ss wrapper). */
.ti-ss.ti-invalid .ti-ss-toggle { border-color: var(--ti-danger); background-color: #FEF2F2; }
.ti-ss.ti-invalid .ti-ss-toggle:focus { box-shadow: 0 0 0 3px rgba(220, 38, 38, .13); }
.ti-ss + .ti-err { margin: 5px 0 0; }
.ti-err { color: var(--ti-danger); font-size: 11.5px; font-weight: 600; margin: -10px 0 12px; display: flex; align-items: center; gap: 5px; }
.ti-err::before { content: '\F33A'; font-family: 'bootstrap-icons'; font-size: 12px; }
.ti-field input::placeholder { color: #A8B0BF; }
.ti-field.is-invalid { border-color: var(--ti-danger); background: #FEF2F2; }
.ti-lbl { font-size: 12.5px; font-weight: 600; color: #374151; display: block; margin-bottom: 6px; }
.ti-lbl .req { color: var(--ti-danger); margin-left: 2px; }
/* Same treatment for the native controls that aren't wrapped in .ti-field. */
.ti-slideover textarea, .ti-slideover .form-control { transition: border-color .15s, background .15s, box-shadow .15s; }
.ti-slideover textarea:focus, .ti-slideover .form-control:focus { background: #fff; border-color: var(--ti-primary); box-shadow: 0 0 0 3px rgba(var(--ti-primary-rgb), .13); outline: none; }

/* ---- Icon button ---- */
.ti-iconbtn { position: relative; width: 38px; height: 38px; border-radius: var(--ti-r-input); background: var(--ti-muted-fill); border: 1px solid var(--ti-border); display: flex; align-items: center; justify-content: center; color: #374151; font-size: 16px; cursor: pointer; }
/* Sidebar counter (My day) — hidden with the labels when the rail collapses,
   because a number with no word next to it means nothing. */
.ti-nav-badge { background: var(--ti-danger); color: #fff; font-size: 10px; font-weight: 800; min-width: 18px;
  height: 18px; border-radius: 999px; display: flex; align-items: center; justify-content: center; padding: 0 5px; flex-shrink: 0; }
.ti-sidebar.collapsed .ti-nav-badge { display: none; }

.ti-badge-dot { position: absolute; top: -4px; right: -4px; background: var(--ti-danger); color: #fff; font-size: 9px; font-weight: 700; min-width: 16px; height: 16px; border-radius: 999px; display: flex; align-items: center; justify-content: center; padding: 0 4px; border: 2px solid #fff; }

/* ---- App shell: sidebar ---- */
.ti-shell { display: flex; height: 100vh; background: linear-gradient(180deg,#FBF7F2,var(--ti-bg)); }
/* Light sidebar (design refresh): white→soft-violet, dark text, coloured icon chips. */
.ti-sidebar { width: 244px; background: linear-gradient(180deg,#FFFFFF,#F7F0E6); border-right: 1px solid #EBE1D4; padding: 10px 10px 14px; display: flex; flex-direction: column; transition: width .22s cubic-bezier(.2,.8,.2,1); flex-shrink: 0; }
.ti-sidebar.collapsed { width: 74px; }
.ti-sidebar.collapsed .ti-nav-label, .ti-sidebar.collapsed .ti-brand-word, .ti-sidebar.collapsed .ti-nav-section, .ti-sidebar.collapsed .ti-nav-chev, .ti-sidebar.collapsed .ti-subnav { display: none !important; }
.ti-sidebar.collapsed .ti-nav-item { justify-content: center; }
.ti-nav-scroll { flex: 1; overflow-y: auto; overflow-x: hidden; margin: 2px -2px 0; padding: 0 2px; }
.ti-logo-mark { width: 34px; height: 34px; border-radius: 10px; background: linear-gradient(135deg,var(--ti-primary),var(--ti-primary-light)); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 17px; flex-shrink: 0; }
.ti-nav-section { font-size: 9.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: rgba(26,19,64,.42); padding: 0 12px; margin: 13px 0 5px; }
.ti-nav-item { display: flex; align-items: center; gap: 11px; padding: 8px 9px; border-radius: 12px; color: #5B5382; font-size: 13.5px; font-weight: 600; cursor: pointer; margin-bottom: 2px; position: relative; transition: background .16s, color .16s; text-decoration: none; }
.ti-nav-item:hover { background: rgba(var(--ti-primary-rgb), .07); color: #1a1340; }
.ti-nav-item.active { background: linear-gradient(90deg,rgba(var(--ti-primary-rgb), .16),rgba(var(--ti-primary-rgb), .03)); color: #1a1340; }
.ti-nav-chip { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; font-size: 15px; flex-shrink: 0; background: rgba(var(--ti-primary-rgb), .09); color: var(--ti-primary); transition: background .16s, color .16s, box-shadow .16s; }
.ti-nav-item.active .ti-nav-chip { background: linear-gradient(135deg,var(--ti-primary),var(--ti-primary-light)); color: #fff; box-shadow: 0 6px 14px -6px rgba(var(--ti-primary-rgb), .7); }
.ti-nav-chip i { font-size: 15px; }
.ti-nav-chev { font-size: 11px; opacity: .55; transition: transform .2s; }
.ti-nav-item.expanded .ti-nav-chev { transform: rotate(90deg); }
/* The arrow is a control of its own (it opens / closes the group): a bigger
   target than an 11px glyph, and it says so on hover. */
.ti-nav-chev[data-nav-toggle] { padding: 6px; margin: -6px -4px -6px 0; border-radius: 7px; opacity: .7; }
.ti-nav-chev[data-nav-toggle]:hover { opacity: 1; background: rgba(var(--ti-primary-rgb), .1); }
.ti-subnav[hidden] { display: none; }
.ti-subnav { display: flex; flex-direction: column; gap: 1px; margin: 1px 0 6px 22px; padding-left: 11px; border-left: 1px solid rgba(26,19,64,.12); animation: fadeUp .22s both; }
.ti-subnav-item { display: flex; align-items: center; gap: 9px; padding: 6px 10px; border-radius: 9px; font-size: 12.5px; font-weight: 600; cursor: pointer; color: #6B6494; text-decoration: none; transition: background .14s, color .14s; }
.ti-subnav-item:hover { background: rgba(var(--ti-primary-rgb), .06); color: var(--ti-primary); }
.ti-subnav-item.active { background: rgba(var(--ti-primary-rgb), .1); color: var(--ti-primary); }
.ti-subnav-item .ti-subdot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .5; flex-shrink: 0; }
.ti-brand-word { color: #1a1340 !important; }
/* The sidebar logo on its own (no name beside it): it gets the row's width. The
   collapsed rail is 74px, so there it shrinks to fit rather than spill over. */
.ti-brand-logo { height: 38px; width: auto; max-width: 100%; object-fit: contain; object-position: left center; flex-shrink: 1; min-width: 0; }
.ti-sidebar.collapsed .ti-brand-logo { height: 32px; max-width: 50px; }
/* An agency's own sidebar logo (Settings → Agency profile → App sidebar): a
   white card with the logo centred and as large as the card allows — the
   platform mark above is drawn bare, an uploaded one gets a surface to sit on. */
.ti-brand-card { display: flex; align-items: center; justify-content: center; height: 64px; margin: 2px 2px 10px; padding: 8px 14px;
  background: var(--ti-surface); border: 1px solid var(--ti-border); border-radius: 14px; text-decoration: none; min-width: 0;
  box-shadow: 0 1px 2px rgba(26, 19, 64, .04); }
.ti-brand-card .ti-brand-logo { height: 100%; max-height: 46px; object-position: center; }
.ti-sidebar.collapsed .ti-brand-card { height: 50px; padding: 4px; margin: 2px 0 10px; }
.ti-sidebar.collapsed .ti-brand-card .ti-brand-logo { max-height: 40px; max-width: 100%; }

/* ---- App shell: topbar ---- */
.ti-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.ti-topbar { height: 62px; background: #fff; border-bottom: 1px solid var(--ti-border); display: flex; align-items: center; gap: 12px; padding: 0 24px; flex-shrink: 0; }
.ti-switcher { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--ti-border); border-radius: var(--ti-r-input); cursor: pointer; flex-shrink: 0; }
.ti-search { display: flex; align-items: center; gap: 10px; background: var(--ti-muted-fill); border: 1px solid var(--ti-border); border-radius: var(--ti-r-input); padding: 9px 14px; flex: 1; max-width: 420px; }
.ti-search input { border: none; background: transparent; outline: none; flex: 1; font-size: 14px; }
.ti-avatar { width: 38px; height: 38px; border-radius: var(--ti-r-input); background: linear-gradient(135deg,var(--ti-primary),var(--ti-primary-light)); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px; }
/* THE PAGE ITSELF NEVER SCROLLS SIDEWAYS. (Owner's report, 2026-09-11.)

   `overflow: auto` is both axes, and this box is the workspace's scroller. So
   one child wider than the window — a long table, an unbroken reference, a row
   of chips — turned the whole page into a horizontal scroller. The topbar and
   the sidebar sit outside this box and stay where they are, so what the agent
   saw was the content sliding out from under its own chrome with the left of
   every card cut off.

   Anything genuinely wide already scrolls inside its own box: .ti-table-scroll
   wraps the tables (see the note further down, which states this same rule),
   the pipeline board carries its own overflow-x, and so does every wide table
   in accounting. Clipping here is what makes those boxes the only way across. */
.ti-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 26px 30px 60px; }

/* ---- KPI cards ---- */
.ti-kpi { background: #fff; border: 1px solid var(--ti-border); border-radius: 14px; padding: 16px 18px; display: flex; flex-direction: column; gap: 4px; }
.ti-kpi-icon { width: 38px; height: 38px; border-radius: 11px; display: flex; align-items: center; justify-content: center; font-size: 17px; }
.ti-kpi-value { font-size: 27px; margin-top: 14px; }
.ti-trend { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 700; padding: 3px 8px; border-radius: 999px; }
.ti-trend-up { color: var(--ti-won); background: #F0FDF4; }
.ti-trend-down { color: var(--ti-danger); background: #FEF2F2; }

/* ---- Tables ---- */
.ti-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ti-table th { padding: 13px 16px; font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px; border-bottom: 1px solid var(--ti-bg); text-align: left; color: var(--ti-subtext); background: var(--ti-muted-fill); }
.ti-table td { padding: 13px 16px; border-bottom: 1px solid #F1F4F9; }
.ti-table tbody tr { cursor: pointer; transition: background .12s; }
.ti-table tbody tr:hover { background: var(--ti-muted-fill); }

/* ---- Avatars (list) ---- */
.ti-av-sm { width: 30px; height: 30px; border-radius: 9px; color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 11.5px; flex-shrink: 0; }

/* ---- Misc ---- */
.ti-todo-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid #F7F0E6; }
.ti-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.ti-toast { position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%); background: #1F2937; color: #fff; padding: 13px 20px; border-radius: 13px; font-size: 13.5px; font-weight: 600; display: flex; align-items: center; gap: 10px; z-index: 60; box-shadow: 0 12px 32px rgba(0,0,0,.28); animation: toastIn .3s both; max-width: min(620px, calc(100vw - 32px)); }
/* Failures sit above success and stay put until dismissed — they carry the reason. */
.ti-toast-bad { bottom: 88px; background: #991B1B; align-items: flex-start; }

/* ---- Slide-over panel + scrim (quick-add lead, record payment, quick-view) ---- */
.ti-scrim { position: fixed; inset: 0; background: rgba(16,24,40,.42); z-index: 40; display: none; animation: fadeIn .2s both; }
.ti-scrim.show { display: block; }
/* A CLOSED PANEL MUST NOT CATCH CLICKS.
 *
 * This was breaking whole screens. A closed panel was hidden by moving it
 * (transform) or fading it (opacity: 0) — and neither of those stops it
 * receiving a click. The centred Add-lead panel is 900px wide and sits in the
 * middle of the viewport, so on the leads list an invisible 824x813 rectangle
 * lay over the table: the quick-filter chips, the lead names, the stage
 * dropdowns and the WhatsApp links inside it were all simply unreachable, with
 * nothing on screen to explain why. Chips further right still worked, which is
 * what made it look like "some things work and some do not".
 *
 * The drawer variant is no safer. It escapes to translateX(100%) — off the
 * right of ITS CONTAINING BLOCK, which is the viewport only while no ancestor
 * has a transform. One animated ancestor and "off-screen" lands mid-page.
 *
 * So closed panels are switched off rather than merely moved: pointer-events
 * stops the clicks, visibility takes them out of the accessibility tree and
 * away from tab focus. visibility is transitioned with a delay so it flips
 * only after the animation has finished, which keeps the fade intact.
 */
.ti-slideover { position: fixed; top: 0; right: 0; bottom: 0; width: 420px; max-width: 94vw; background: #fff; z-index: 41; padding: 22px; box-shadow: -12px 0 40px rgba(16,24,40,.14); overflow-y: auto; transform: translateX(100%); visibility: hidden; pointer-events: none; transition: transform .3s cubic-bezier(.2,.8,.2,1), visibility 0s linear .3s; }
.ti-slideover.show { transform: none; visibility: visible; pointer-events: auto; transition: transform .3s cubic-bezier(.2,.8,.2,1), visibility 0s; }

/* CENTRED MODAL VARIANT.
   A 420px rail is right for a three-field panel and wrong for the Add-lead
   form, which has fifteen fields across three sections — on that one the agent
   scrolled a narrow column and never saw the trip and the handling at once.
   Opt-in (`.is-centred`) so the other slide-overs keep the drawer they suit. */
.ti-slideover.is-centred {
  top: 50%; left: 50%; right: auto; bottom: auto;
  width: min(900px, 94vw); max-height: 90vh;
  border-radius: var(--ti-r-card, 18px);
  box-shadow: 0 24px 70px rgba(16,24,40,.22);
  transform: translate(-50%, -46%) scale(.98);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: transform .24s cubic-bezier(.2,.8,.2,1), opacity .18s ease, visibility 0s linear .24s;
}
.ti-slideover.is-centred.show {
  transform: translate(-50%, -50%) scale(1); opacity: 1;
  visibility: visible; pointer-events: auto;
  transition: transform .24s cubic-bezier(.2,.8,.2,1), opacity .18s ease, visibility 0s;
}

/* Two fields across in the wide panel, stacked once there is no room. */
.qa-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
@media (max-width: 720px) { .qa-pair { grid-template-columns: 1fr; } }

/* The header stays put while the body scrolls, so "Add lead" and the close
   button are reachable from the bottom of a long form. */
.ti-slideover.is-centred .ti-slideover-hd {
  position: sticky; top: -22px; z-index: 2;
  background: #fff; margin: -22px -22px 14px; padding: 18px 22px 14px;
  border-bottom: 1px solid var(--ti-border);
  border-radius: var(--ti-r-card, 18px) var(--ti-r-card, 18px) 0 0;
}

/* Two columns once there is room for them — this is the whole point of the
   wider panel. Sections and full-width controls opt out via .ti-col-full. */
@media (min-width: 860px) {
  .ti-modal-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 26px; align-items: start; }
  .ti-modal-cols > .ti-col-full { grid-column: 1 / -1; }
}

@media (max-width: 720px) {
  .ti-slideover.is-centred { width: 100vw; max-height: 100vh; height: 100%; border-radius: 0;
    top: 0; left: 0; transform: translateY(12px); }
  .ti-slideover.is-centred.show { transform: none; }
}
.ti-slideover-hd { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.ti-stepper { display: inline-flex; align-items: center; gap: 10px; }
/* Both buttons carry the same weight — a white minus next to a solid purple plus
   reads as "minus is disabled". Dimming is reserved for actually being at zero. */
.ti-stepbtn { width: 30px; height: 30px; border-radius: 9px; border: 1.5px solid #DDD6FE; background: var(--ti-brand-tint); display: flex; align-items: center; justify-content: center; color: var(--ti-primary); cursor: pointer; font-size: 15px; font-weight: 700; user-select: none; transition: background .13s, transform .08s, border-color .13s; }
.ti-stepbtn:hover { background: #DFD9FF; border-color: var(--ti-primary); }
.ti-stepbtn:active { transform: scale(.9); }
.ti-stepbtn.is-off { background: #F4F5F7; border-color: var(--ti-border); color: #C2C8D2; cursor: not-allowed; }
.ti-stepbtn.is-off:hover { background: #F4F5F7; border-color: var(--ti-border); }
.ti-stepbtn.pri { background: var(--ti-primary); color: #fff; border-color: var(--ti-primary); }
.ti-stepbtn.pri:hover { background: #4B3FD0; }

/* ---- Mobile bottom tab bar (design 4: 4–5 key actions, thumb-reachable) ---- */
.ti-bottombar { display: none; }

/* ---- Responsive ---- */
@media (max-width: 860px) {
  .ti-sidebar { position: fixed; z-index: 50; height: 100vh; transform: translateX(-100%); transition: transform .22s cubic-bezier(.2,.8,.2,1); box-shadow: 8px 0 40px rgba(16,24,40,.2); }
  .ti-sidebar.open { transform: none; }
  .ti-search { display: none; }
  .ti-body { padding: 18px 16px 86px; }
  .ti-topbar { padding: 0 14px; }

  .ti-drawer-scrim { position: fixed; inset: 0; background: rgba(16,24,40,.42); z-index: 49; display: none; }
  .ti-drawer-scrim.show { display: block; }

  .ti-bottombar {
    display: flex; position: fixed; bottom: 0; left: 0; right: 0; z-index: 45;
    background: #fff; border-top: 1px solid var(--ti-border); padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
    box-shadow: 0 -4px 20px rgba(16,24,40,.06);
  }
  .ti-bottombar a {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 6px 0; color: var(--ti-faint); font-size: 10.5px; font-weight: 600; text-decoration: none;
  }
  .ti-bottombar a.active { color: var(--ti-primary); }
  .ti-bottombar a i { font-size: 19px; }
  .ti-bottombar .ti-bb-fab {
    flex: 0 0 auto; width: 46px; height: 46px; margin-top: -18px; border-radius: 16px;
    background: var(--ti-grad-primary); color: #fff; box-shadow: 0 6px 16px rgba(var(--ti-primary-rgb), .4);
    justify-content: center; font-size: 22px;
  }
  .ti-bottombar .ti-bb-fab i { font-size: 22px; }
  /* A panel open (Add lead, a chat…) has the screen: the bar sat on top of it
     and over its Save button. The scrim is shown with every panel. */
  #ti-scrim.show ~ .ti-bottombar { display: none; }
}

/* THE TOP BAR ON A PHONE. (QA 2026-10-31.) The agency and branch switchers
   kept their names and the icons kept their size, so at 393px the agency name
   wrapped onto three lines underneath the icons. Below 576px the switchers
   are icons (the menu each opens still names the agency / branch) and the
   buttons tighten; on the narrowest phones the world clock and calculator —
   which the phone itself has — step aside. */
@media (max-width: 575px) {
  .ti-topbar { gap: 6px; padding: 0 10px; }
  .ti-top-left { gap: 6px !important; }
  .ti-top-left .ti-switcher { padding: 8px 9px; gap: 5px; }
  .ti-top-left .ti-switcher > span { display: none; }
  .ti-top-right { gap: 6px !important; }
  .ti-top-right .ti-iconbtn { width: 34px; height: 34px; }
}
@media (max-width: 430px) {
  #tiWcBtn, #tiCalcBtn { display: none; }
}

/* ===== Searchable select + phone country dropdown (searchable.js) =====
   These enhance native <select data-searchable> and <x-phone-input>. Without them
   the native control shows alongside the custom one (looks doubled) and the panel
   renders inline instead of as a closing overlay. */
.ti-ss { position: relative; }
/* Keep the real <select> in the DOM (so the form still submits) but hidden. */
.ti-ss-native { display: none !important; }

/* A REQUIRED SEARCHABLE SELECT THAT WAS LEFT EMPTY.
   The native <select> is display:none, so the browser has nowhere to put its
   own message — searchable.js draws this one instead. Sits under the visible
   toggle and takes its own line, so a long sentence is readable rather than
   squeezed beside the control. */
.ti-ss.is-invalid > .ti-ss-toggle { border-color: #DC2626; }
.ti-ss.is-invalid > .ti-ss-toggle:focus { box-shadow: 0 0 0 3px rgba(220, 38, 38, .15); }
.ti-ss-err {
  flex: 1 0 100%; min-width: 0;
  margin-top: 6px;
  display: flex; gap: 6px; align-items: flex-start;
  color: #B91C1C; font-size: 12px; font-weight: 700; line-height: 1.4;
}
.ti-ss-err::before { content: "\F33A"; font-family: "bootstrap-icons"; font-weight: 400; flex-shrink: 0; }
.ti-ss-toggle {
  display: flex !important; align-items: center; justify-content: space-between;
  width: 100%; text-align: left; cursor: pointer; background: #fff;
  min-height: 44px; border: 1.5px solid var(--ti-border); border-radius: 12px;
  padding: 9px 14px; font-size: 13.5px; color: var(--ti-text);
}
.ti-ss-toggle { transition: border-color .15s, box-shadow .15s; }
.ti-ss-toggle:hover { border-color: #F0B590; }
/* Match .ti-field so dropdowns and text inputs respond to the agent identically. */
.ti-ss-toggle:focus { border-color: var(--ti-primary); box-shadow: 0 0 0 3px rgba(var(--ti-primary-rgb), .13); outline: none; }
/* While the panel is open the toggle stays lit, even if focus moved to the search box. */
.ti-ss:has(.ti-ss-panel.show) .ti-ss-toggle { border-color: var(--ti-primary); box-shadow: 0 0 0 3px rgba(var(--ti-primary-rgb), .13); }
.ti-ss-toggle.text-muted { color: var(--ti-faint); }
/* A long option trims to one line instead of wrapping out of the box; the full
   text is on the button's title (searchable.js). min-width:0 all the way down,
   or a grid or flex cell refuses to let the label shrink at all. */
.ti-ss, .ti-ss-toggle { min-width: 0; }
.ti-ss-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ti-phone { position: relative; }
.ti-phone .input-group { flex-wrap: nowrap; }

/* The floating panel — shared by search-select and phone. Width = the field
   (no min-width, so a narrow half-row field doesn't spill onto the backdrop). */
.ti-ss-panel {
  position: absolute; z-index: 1090; top: calc(100% + 5px); left: 0; right: 0;
  background: #fff; border: 1px solid var(--ti-border); border-radius: 12px;
  /* Heavier than it was. On a cream canvas a soft shadow and a pale border
     left the open panel looking like part of the card underneath it, which is
     what made it read as "overlapping" rather than "on top of". */
  box-shadow: 0 18px 44px rgba(26,19,64,.28), 0 2px 6px rgba(26,19,64,.10);
  border-color: #D8CBB8; padding: 6px; display: none;
  /* A narrow field (the "Whose day" picker is ~70px) must not squeeze names to "M…":
     the panel is at least the field wide, and grows to fit its longest option. */
  min-width: max(100%, 200px); width: max-content; max-width: min(360px, 92vw);
  /* Its own alignment, whatever it sits in: inside a right-aligned table cell
     the options read right-aligned under a left-aligned value and search box. */
  text-align: left;
}
.ti-ss-panel.align-right { left: auto; right: 0; }
/* Phone country panel needs a little more room for flags + names. */
.ti-phone .ti-ss-panel { min-width: 260px; }
/* Flip above the field when there's no room below (JS toggles .drop-up). */
.ti-ss-panel.drop-up { top: auto; bottom: calc(100% + 5px); }
.ti-ss-panel.show { display: block; animation: ssPop .15s cubic-bezier(.2,.8,.2,1); }
/* A card (or grid cell) whose search-select is open must float above its neighbours,
   or the dropdown renders behind the card beside/below it. */
.ti-card:has(.ti-ss-panel.show) { position: relative; z-index: 40; }
/* …and must not CLIP it. Table cards are overflow:hidden (for their rounded
   corners), so a list opening under the Rows picker at the foot of the card was
   cut off at the card's edge — a sliver of "Search…" and empty space where the
   options should be. Only while a list is open; the corners come back on close. */
.ti-card:has(.ti-ss-panel.show) { overflow: visible !important; }
.ti-ss-search { padding: 2px 2px 6px; }
.ti-ss-search input, .ti-ss-panel .form-control { font-size: 13px; border-radius: 9px; }
.ti-ss-list { max-height: 240px; overflow-y: auto; }
.ti-ss-item {
  padding: 8px 11px; border-radius: 8px; cursor: pointer; font-size: 13.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ti-ss-item:hover { background: var(--ti-soft-fill); }
.ti-ss-item.active { background: var(--ti-brand-tint, var(--ti-brand-tint)); color: var(--ti-primary); font-weight: 600; }
.ti-ss-item.ti-ss-add { color: var(--ti-primary); font-weight: 600; border-top: 1px dashed var(--ti-border); margin-top: 2px; }
.ti-ss-empty { padding: 12px; text-align: center; color: var(--ti-faint); font-size: 13px; }

/* Phone country rows */
.ti-phone-item { display: flex; align-items: center; gap: 8px; }
.ti-phone-item-flag { font-size: 15px; }
.ti-phone-item-name { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.ti-phone-item-code { margin-left: auto; }
.ti-phone-toggle { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }

@keyframes ssPop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.ti-pulse { animation: pulse 1.4s ease-in-out infinite; }

/* ===== Motion polish (entrance stagger + interactive hovers) ===== */
/* Cards slide up on first paint; stagger the first few for a layered feel. */
.ti-anim-fadein > .ti-card,
.ti-anim-fadeup > .ti-card { animation: cardLift .5s both; }
.ti-anim-fadein > .ti-card:nth-child(2){ animation-delay:.04s }
.ti-anim-fadein > .ti-card:nth-child(3){ animation-delay:.08s }
.ti-anim-fadein > .ti-card:nth-child(4){ animation-delay:.12s }
.ti-anim-fadein > .ti-card:nth-child(5){ animation-delay:.16s }
.ti-anim-fadein > .ti-card:nth-child(6){ animation-delay:.20s }

/* Clickable table rows get a clear hover affordance. */
.ti-table tbody tr[onclick] { cursor: pointer; transition: background .13s; }
.ti-table tbody tr[onclick]:hover { background: var(--ti-soft-fill); }

/* Buttons & pills feel a touch more alive. */
.ti-btn:active { transform: translateY(1px) scale(.99); }
.ti-iconbtn { transition: background .14s, color .14s, transform .12s; }
.ti-iconbtn:hover { background: var(--ti-brand-tint); color: var(--ti-primary); }

/* Respect reduced-motion preferences. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* ===== Scroll smoothness =====
   Looping decoration (the live map's SMIL paths, pulsing dots, marquees) repaints
   on the main thread every frame. That is fine on its own and awful while the user
   is scrolling, because the same thread has to produce frames for both.

   Two rules, applied by ti-motion.js:
   - .ti-scrolling on <html> while a scroll is in flight → freeze the decoration.
   - .is-offscreen on a heavy block the viewport has left → stop paying for it at all. */
html.ti-scrolling [data-decor],
html.ti-scrolling [data-decor] * { animation-play-state: paused !important; }
[data-decor].is-offscreen,
[data-decor].is-offscreen * { animation-play-state: paused !important; }

/* Skip layout+paint for big blocks that are nowhere near the viewport. The size hint
   keeps the scrollbar honest so the page doesn't jump as they come into view. */
.ti-defer { content-visibility: auto; contain-intrinsic-size: auto 420px; }

/* ══════════════════════════════════════════════════════════════════════════
   Table toolbar — column picker + saved views
   ══════════════════════════════════════════════════════════════════════════ */

.ti-tbar { display: inline-flex; gap: 8px; align-items: center; }

.ti-tbar-drop { position: relative; }
.ti-tbar-drop > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: 6px;
}
.ti-tbar-drop > summary::-webkit-details-marker { display: none; }
.ti-tbar-drop[open] > summary { background: var(--ti-soft-fill); }

/* OPENS WHERE IT FITS. This was pinned to the button's right edge, which is
   right for a toolbar at the right of a page (Leads) and wrong everywhere else:
   on Payments the button sits at the LEFT, the menu grew leftwards, and
   .ti-body (overflow-x: hidden) cut it off under the sidebar. It now opens
   rightwards from the button, and table-views.js adds .is-end to flip it back
   when that would run past the right edge of the page, and .is-up to open it
   upwards when there is more room above the button than below. */
.ti-tbar-menu {
  position: absolute; left: 0; right: auto; top: calc(100% + 6px); z-index: 40;
  min-width: 240px; max-height: 70vh; overflow: auto;
  background: #fff; border: 1px solid var(--ti-border); border-radius: 12px;
  box-shadow: 0 18px 44px rgba(16, 24, 40, .16); padding: 8px;
}

.ti-tbar-menu.is-end { left: auto; right: 0; }
.ti-tbar-menu.is-up { top: auto; bottom: calc(100% + 6px); }

.ti-tbar-menu-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  color: var(--ti-faint); padding: 6px 8px 8px;
}

.ti-tbar-cols { display: grid; gap: 1px; }
.ti-tbar-col {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 8px; border-radius: 8px; cursor: pointer; font-size: 13px;
}
.ti-tbar-col:hover { background: var(--ti-soft-fill); }
.ti-tbar-col.is-locked { opacity: .55; cursor: not-allowed; }
.ti-tbar-col i { margin-left: auto; font-size: 10px; color: var(--ti-faint); }

.ti-tbar-views { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 1px; }
.ti-tbar-views li { display: flex; align-items: center; gap: 4px; border-radius: 8px; padding-right: 4px; }
.ti-tbar-views li:hover { background: var(--ti-soft-fill); }
.ti-tbar-views li.is-active { background: var(--ti-soft-fill); }
.ti-tbar-views li form { display: inline; margin: 0; }
.ti-tbar-view-name {
  flex: 1; display: flex; align-items: baseline; gap: 7px;
  padding: 8px; font-size: 13px; font-weight: 600; color: inherit; text-decoration: none;
}
.ti-tbar-view-name small { color: var(--ti-faint); font-weight: 500; font-size: 11px; }

.ti-tbar-save { border-top: 1px solid var(--ti-bg); margin-top: 6px; padding: 4px 8px 8px; }
.ti-tbar-hint { font-size: 11.5px; color: var(--ti-faint); margin: 0 0 8px; line-height: 1.5; }
.ti-tbar-default { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ti-subtext); margin-top: 9px; cursor: pointer; }
.ti-tbar-clear {
  display: flex; align-items: center; gap: 6px; font-size: 12px;
  padding: 8px; color: var(--ti-subtext); text-decoration: none; border-top: 1px solid var(--ti-bg);
}
.ti-tbar-clear:hover { color: var(--ti-primary); }
.ti-linkish { background: none; border: 0; padding: 0; font: inherit; color: var(--ti-primary); cursor: pointer; text-transform: none; letter-spacing: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   Responsive tables
   A wide table on a phone used to squash every column to unreadable width.
   It now scrolls sideways inside its own box — the page itself never does —
   and the first column stays put so a scrolled row is still identifiable.
   ══════════════════════════════════════════════════════════════════════════ */

.ti-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
}
.ti-table-scroll > .ti-table { min-width: 760px; }

@media (max-width: 860px) {
  .ti-table th, .ti-table td { padding: 11px 12px; }
  .ti-table { font-size: 12.5px; }

  /* Keep the identifying column in view while the rest scrolls under it. */
  .ti-table-scroll .ti-table thead th:first-child,
  .ti-table-scroll .ti-table tbody td:first-child {
    position: sticky; left: 0; z-index: 2;
    background: #fff;
    box-shadow: 1px 0 0 var(--ti-border);
  }
  .ti-table-scroll .ti-table thead th:first-child { background: var(--ti-muted-fill); z-index: 3; }
  .ti-table-scroll .ti-table tbody tr:hover td:first-child { background: var(--ti-muted-fill); }

  /* Filter bars: one control per row rather than a squeezed strip. */
  .ti-filters { flex-direction: column; align-items: stretch; }
  .ti-filters > * { width: 100%; }

  .ti-tbar { flex-wrap: wrap; }
  .ti-tbar-menu { position: fixed; left: 12px; right: 12px; top: auto; min-width: 0; max-height: 60vh; }
}

@media (max-width: 560px) {
  .ti-table-scroll > .ti-table { min-width: 620px; }
  .ti-page-head { flex-direction: column; align-items: flex-start; gap: 10px; }
  .ti-page-head .ti-btn { width: 100%; justify-content: center; }
}

/* Ask DMC → "Other DMCs on your list" (untagged for this destination). */
.dmc-others { margin-top: 12px; border-top: 1px dashed var(--ti-border); padding-top: 12px; }
.dmc-others > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13px; font-weight: 600; color: var(--ti-subtext);
}
.dmc-others > summary::-webkit-details-marker { display: none; }
.dmc-others > summary small { font-weight: 500; color: var(--ti-faint); font-size: 11.5px; }
.dmc-others > summary > .bi-chevron-right { transition: transform .16s; font-size: 11px; }
.dmc-others[open] > summary > .bi-chevron-right { transform: rotate(90deg); }
.dmc-others > summary:hover { color: var(--ti-primary); }

/* The confirm-dialog styles used to live here. They now ship inside
   ti-dialog.js: the dialog is built entirely by that script, and a deploy that
   carried the script without this stylesheet rendered its markup raw at the
   foot of the page. One file, so that cannot happen again. */

/* ── Table tools: tabs, column picker, saved filters (table-tools.js) ───────
   The tab strip is a segmented control rather than underlined tabs — these sit
   inside a page that already has a pill sub-nav, and two underlined rows read
   as two navigations. */
.tt-tabs { display: flex; gap: 4px; padding: 4px; background: var(--ti-muted-fill);
    border: 1px solid var(--ti-border); border-radius: 12px; flex-wrap: wrap; }
.tt-tab { appearance: none; border: 0; background: transparent; font: inherit; font-size: 13px;
    font-weight: 650; color: var(--ti-subtext); padding: 8px 15px; border-radius: 9px; cursor: pointer;
    display: inline-flex; align-items: center; gap: 7px; transition: background .13s, color .13s; }
.tt-tab:hover { color: var(--ti-text); }
.tt-tab.is-on { background: #fff; color: var(--ti-text); box-shadow: 0 1px 2px rgba(16, 24, 40, .07); }
.tt-tab .tt-tab-n { font-size: 11px; font-weight: 700; padding: 1px 7px; border-radius: 999px;
    background: var(--ti-border); color: var(--ti-subtext); }
.tt-tab.is-on .tt-tab-n { background: rgba(var(--ti-primary-rgb), .13); color: var(--ti-primary); }

/* The column picker and saved-view popover that stood here are gone: both
   already existed as <x-table-toolbar> (table-views.js), which stores the
   choices server-side against the person rather than in one browser. Only the
   tab strip above is this file's own. */

/* ── AI Assistant panel (header button → #panel-assistant) ─────────────────
   Violet, not terracotta: violet is the AI accent across the product and the
   distinction is deliberate — an AI surface should never be mistaken for one
   the agency's own data drives. */
.aia-you { background: var(--ti-muted-fill); border: 1px solid var(--ti-border); border-radius: 12px 12px 12px 4px;
    padding: 10px 13px; font-size: 13px; color: var(--ti-text); margin-bottom: 12px; }
.aia-answer { font-size: 13.5px; line-height: 1.68; color: var(--ti-text); }
.aia-acts { display: flex; flex-direction: column; gap: 7px; margin-top: 14px; }
.aia-act { display: flex; align-items: center; gap: 4px; text-decoration: none; font-size: 12.5px; font-weight: 650;
    color: #6D28D9; background: #F5F3FF; border: 1px solid #DDD6FE; border-radius: 10px; padding: 9px 12px; }
.aia-act:hover { background: #EDE9FE; border-color: #C4B5FD; color: #5B21B6; }
.aia-act i { font-size: 16px; }
.aia-note { display: flex; gap: 9px; align-items: flex-start; border-radius: 10px; padding: 9px 12px;
    font-size: 12px; line-height: 1.55; margin-bottom: 12px; }
.aia-note i { margin-top: 1px; flex-shrink: 0; }
.aia-note.is-warn { background: #FFFBEB; border: 1px solid #FDE68A; color: #78350F; }
.aia-note.is-bad { background: #FEF2F2; border: 1px solid #FECACA; color: #7F1D1D; }
.aia-send { border: 0; background: transparent; color: var(--ti-faint); cursor: pointer; padding: 0 2px; font-size: 14px; }
.aia-send:hover { color: #7C3AED; }
.aia-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.aia-chip { appearance: none; border: 1px solid var(--ti-border); background: #fff; color: var(--ti-subtext);
    border-radius: 999px; padding: 6px 12px; font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer; }
.aia-chip:hover { border-color: #C4B5FD; background: #F5F3FF; color: #6D28D9; }
.aia-foot { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--ti-border);
    display: flex; gap: 8px; align-items: flex-start; font-size: 11.5px; line-height: 1.55; color: var(--ti-faint); }
.aia-foot i { margin-top: 1px; flex-shrink: 0; }
/* Loading: three shimmering lines, so the wait looks like an answer forming. */
.aia-skel span { display: block; height: 12px; border-radius: 6px; margin-bottom: 9px;
    background: linear-gradient(90deg, var(--ti-muted-fill) 25%, #EFEAE2 50%, var(--ti-muted-fill) 75%);
    background-size: 200% 100%; animation: aia-shimmer 1.1s infinite; }
.aia-skel span:nth-child(2) { width: 88%; } .aia-skel span:nth-child(3) { width: 62%; }
@keyframes aia-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ── Currency switch (currency-switch.js) ──────────────────────────────────
   The .fx-opt / .fx-toggle pair began life inline on the DMC compare screen;
   they live here now that a second screen needs them. */
.fx-switch { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fx-switch-lbl { font-size: 12px; color: var(--ti-subtext); display: inline-flex; align-items: center; gap: 5px; }
.fx-switch-lbl i { color: var(--ti-primary); }
.fx-switch .fx-opt {
    border: 1px solid var(--ti-border); background: #fff; color: var(--ti-subtext);
    font: inherit; font-size: 11.5px; font-weight: 700; padding: 5px 11px; border-radius: 999px; cursor: pointer;
}
.fx-switch .fx-opt:hover { border-color: var(--ti-primary); color: var(--ti-primary); }
.fx-switch .fx-opt.on { background: var(--ti-primary); border-color: var(--ti-primary); color: #fff; }

/* THE DROPDOWN THAT REPLACED THE PILLS.
   The list is data — it grows with the currencies the agency deals in — so a
   row of buttons was a layout that broke on the tenth. Sized to sit inline
   beside its label rather than as a form field: the searchable enhancement
   swaps the <select> for a full-width button.form-select, which would take the
   width of the card it sits in. */
.fx-switch .fx-sel,
.fx-switch .ti-ss { min-width: 132px; }
.fx-switch .ti-ss-toggle {
    font-size: 11.5px; font-weight: 700; color: var(--ti-subtext);
    padding: 5px 26px 5px 11px; min-height: 0; height: auto; border-radius: 999px;
    border: 1px solid var(--ti-border); background-color: #fff; background-size: 10px;
}
.fx-switch .ti-ss-toggle:hover { border-color: var(--ti-primary); color: var(--ti-primary); }
.fx-switch .ti-ss-panel { min-width: 200px; }
/* Before searchable.js has enhanced it — and if the script is unavailable at
   all, in which case this stays the control and must still look like one. */
.fx-switch select.fx-sel {
    font: inherit; font-size: 11.5px; font-weight: 700; color: var(--ti-subtext);
    border: 1px solid var(--ti-border); border-radius: 999px; padding: 5px 11px;
    background: #fff; cursor: pointer;
}

/* A converted figure is an approximation and reads as one — never the same
   weight as the price that was actually quoted. */
.fx-amt.is-converted { color: var(--ti-subtext); font-style: italic; }

.fx-note {
    display: flex; gap: 9px; align-items: flex-start; margin-top: 10px;
    background: #FFFBEB; border: 1px solid #FDE68A; color: #78350F;
    border-radius: 11px; padding: 9px 12px; font-size: 12px; line-height: 1.55;
}
.fx-note i { margin-top: 1px; flex-shrink: 0; }

/* ---- AI spend, in the top bar --------------------------------------------
   Quiet by default: it is a fact, not an alert. Only the balance turns amber,
   and only once it is low enough to be about to interrupt someone's work. */
.ti-aispend { display: inline-flex; align-items: center; gap: 7px; text-decoration: none;
  background: var(--ti-muted-fill); border: 1px solid var(--ti-border); border-radius: 999px;
  padding: 6px 12px; font-size: 12.5px; font-weight: 600; color: var(--ti-subtext);
  white-space: nowrap; transition: border-color .15s, color .15s; }
.ti-aispend:hover { border-color: var(--ti-primary); color: var(--ti-primary); }
.ti-aispend > i { font-size: 13px; }
.ti-aispend-v { font-weight: 800; color: var(--ti-text); font-variant-numeric: tabular-nums; }
.ti-aispend:hover .ti-aispend-v { color: var(--ti-primary); }
.ti-aispend-left { font-size: 11px; font-weight: 600; color: var(--ti-faint);
  padding-left: 7px; border-left: 1px solid var(--ti-border); font-variant-numeric: tabular-nums; }
.ti-aispend-left.is-low { color: #B45309; }

@media (max-width: 640px) { .ti-aispend-left { display: none; } }

/* ── Column reordering, in the column picker ─────────────────────────────
   Two small chevrons per row. They sit inside the <label> that toggles the
   column, so the JS stops the click reaching the checkbox — pressing "move"
   must never also hide the thing you are moving. */
.ti-tbar-col{display:flex;align-items:center;gap:8px}
.ti-tbar-move{margin-left:auto;display:inline-flex;gap:2px;flex-shrink:0}
.ti-tbar-move button{
  width:20px;height:18px;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--ti-border);background:#fff;border-radius:5px;
  color:var(--ti-faint);cursor:pointer;padding:0;font-size:9px;line-height:1}
.ti-tbar-move button:hover{border-color:var(--ti-primary);color:var(--ti-primary)}
.ti-tbar-col.is-locked .ti-tbar-move{opacity:.35;pointer-events:none}

/* ── Dropdown options in the portal's own font ───────────────────────────
   A <select> takes font:inherit and looks right closed, but its <option>
   children are drawn by the browser and do NOT inherit — so every native
   dropdown opened into a different typeface than the page around it. Setting
   the family on the option itself is the only thing that reaches them.

   Applied to every select rather than one, because the mismatch was never
   specific to the tax picker: it was every dropdown in the product. */
select option,
select optgroup {
  font-family: var(--ti-font-body, 'Instrument Sans', system-ui, sans-serif);
  font-size: 13px;
  color: var(--ti-text, #1A1340);
}

/* ==========================================================================
   ONE TYPE SCALE FOR EVERY FORM CONTROL. (Owner's call — "the +91 font is
   different from the theme font".)

   It was not the family — every control resolves to Instrument Sans. It was the
   SIZE, and there were three of them in a single panel: .ti-field inputs at
   14px, the searchable selects at 13.5px, and anything left as a raw Bootstrap
   control — the phone's country button, the phone number box, a bare textarea —
   at Bootstrap's 1rem default of 16px, in a 38px-tall box beside 41-48px
   fields. Next to each other that reads as a different typeface.

   Sized here rather than per screen, because the mismatch was never specific to
   one panel: it appeared wherever a raw .form-control sat beside a .ti-field.
   ========================================================================== */
.ti-field input,
.ti-field select,
.ti-field textarea { font-size: 13.5px; }

.ti-phone .form-control,
.ti-phone-toggle,
.ti-slideover .form-control,
.ti-slideover .form-select,
.ti-slideover textarea,
.ti-card .form-control,
.ti-card .form-select,
.ti-dmcm .form-control,
.ti-dmcm .form-select { font-size: 13.5px; }

/* The phone group is two controls pretending to be one field, so it has to
   stand exactly as tall as a .ti-field beside it — 11px of padding on 13.5px
   text, the same arithmetic .ti-field uses. */
.ti-phone .form-control,
.ti-phone-toggle { padding-top: 11px; padding-bottom: 11px; }

/* SMALL SCREENS MOVE AS ONE.
   iOS Safari zooms the page when a focused input is under 16px, so on a phone
   every control goes UP together rather than the raw Bootstrap ones staying
   large on their own. Same rule as above, one size bigger — the mismatch is
   what was wrong, not the scale. */
@media (max-width: 575.98px) {
  .ti-field input,
  .ti-field select,
  .ti-field textarea,
  .ti-phone .form-control,
  .ti-phone-toggle,
  .ti-ss-toggle,
  .ti-slideover .form-control,
  .ti-slideover .form-select,
  .ti-slideover textarea,
  .ti-card .form-control,
  .ti-card .form-select { font-size: 16px; }
}

/* ONE HEIGHT TOO, not only one size.
   A date input, a number input and a text input do not render the same height
   from the same padding — the panel measured 44 / 46 / 48 / 50 down one column,
   which reads as sloppy even when nothing is misaligned. A floor on the box and
   a fixed line-height on what sits in it settles them. Selects that wrap to two
   lines still grow; this is a minimum, not a height. */
.ti-field,
.ti-ss-toggle,
.ti-phone .input-group { min-height: 42px; }
.ti-field input,
.ti-field select,
.ti-field textarea { line-height: 1.35; }

@media (max-width: 575.98px) {
  .ti-field,
  .ti-ss-toggle,
  .ti-phone .input-group { min-height: 48px; }
}

/* ==========================================================================
   FORM SECTIONS AND OPTIONAL BLOCKS.

   Both lived in resources/views/app/leads/_quick_add.blade.php, a partial that
   only the leads LIST pulls in — while the lead page's Edit panel uses the same
   markup. On that page "1 Who is it" was an unstyled number next to plain text,
   and <details> kept the browser's own ▶ marker. Shared idiom, shared file.
   ========================================================================== */
.ti-sec { display: flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ti-primary);
  margin: 22px 0 12px; padding-top: 16px; border-top: 1px solid var(--ti-border); }
.ti-sec:first-of-type { border-top: none; padding-top: 0; margin-top: 4px; }
.ti-sec-n { width: 19px; height: 19px; border-radius: 50%; background: var(--ti-primary); color: #fff;
  display: grid; place-items: center; font-size: 10.5px; letter-spacing: 0; flex-shrink: 0; }

.ti-more { border: 1px dashed #D8C8B4; border-radius: 12px; padding: 11px 13px; margin-bottom: 14px;
  background: var(--ti-soft-fill); }
.ti-more summary { cursor: pointer; font-size: 12.5px; font-weight: 700; color: var(--ti-primary); list-style: none; }
.ti-more summary::-webkit-details-marker { display: none; }
.ti-more summary span { font-weight: 500; color: var(--ti-faint); font-size: 11.5px; }
.ti-more[open] summary { margin-bottom: 2px; }

/* The disclosure line grows with the controls on a phone, for the same reason
   they do — a 12.5px summary between 16px fields reads as a different design. */
@media (max-width: 575.98px) {
  .ti-more summary { font-size: 14px; }
  .ti-more summary span { font-size: 13px; }
}

/* ==========================================================================
   TWO-UP AND THREE-UP FIELD ROWS.

   These rows were `display:flex` with `flex:1` columns and nothing else, which
   overflows: a flex item's default min-width is auto, so a column can never
   shrink below the intrinsic width of the control inside it. A date input at
   16px is wide, and the Anniversary field was measured hanging 52px past the
   edge of its own panel — off-screen, on a form the agent is filling in.

   min-width:0 lets them shrink; below 480px they stop pretending and wrap,
   because three date fields across a 353px panel is not a layout, it is four
   truncated characters each.
   ========================================================================== */
.ti-row2, .ti-row3 { display: flex; gap: 10px; }
.ti-row2 > *, .ti-row3 > * { flex: 1 1 0; min-width: 0; }
.ti-row2 > * > .ti-field, .ti-row3 > * > .ti-field { min-width: 0; }
.ti-row2 input, .ti-row3 input { min-width: 0; }

@media (max-width: 479.98px) {
  .ti-row2, .ti-row3 { flex-wrap: wrap; }
  .ti-row2 > *, .ti-row3 > * { flex: 1 1 100%; }
}
/* Nights is a two-digit box, not a third of the row — it keeps its own width
   while the two date fields share what is left, and joins the wrap below 480px
   like everything else. */
.ti-nights-col { flex: 0 0 96px; }
@media (max-width: 479.98px) { .ti-nights-col { flex: 1 1 100%; } }

/* "Came via a referral?" — one phrase per line when it has to break. */
.ld-reftoggle { display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 12.5px; font-weight: 700; color: #7C3AED; cursor: pointer; }
.ld-reftoggle-t { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.ld-reftoggle-n { color: var(--ti-faint); font-weight: 600; }
.ld-reftoggle-c { font-size: 10px; margin-left: auto; }
@media (max-width: 479.98px) {
  .ld-reftoggle-n { flex-basis: 100%; margin-left: 22px; font-size: 11.5px; }
  .ld-reftoggle-c { margin-left: 0; }
}

/* ══ ARRANGE COLUMNS ═══════════════════════════════════════════════════════
   Drag-to-reorder, in a dialog rather than inside the Columns menu — a drag
   handle in that menu fights the menu's own scrolling, which is why the
   chevrons were built first and why they stay. Here the columns are laid out
   left to right exactly as the table has them, and you push one along.
   ========================================================================== */
.ti-tbar-arrange{
  display:flex;align-items:center;gap:7px;width:100%;margin:0 0 8px;
  border:1px dashed var(--ti-border);background:var(--ti-soft-fill);border-radius:10px;
  padding:8px 11px;font-size:12px;font-weight:700;color:var(--ti-primary);
  cursor:pointer;font-family:inherit}
.ti-tbar-arrange:hover{border-color:var(--ti-primary);background:var(--ti-brand-tint)}

.tvo-back{
  position:fixed;inset:0;z-index:1200;background:rgba(30,22,14,.42);
  display:flex;align-items:center;justify-content:center;padding:18px}
.tvo-box{
  background:#fff;border:1px solid var(--ti-border);border-radius:18px;
  width:min(720px,100%);max-height:88vh;overflow:auto;padding:18px 20px 16px;
  box-shadow:0 24px 60px -20px rgba(30,22,14,.45)}
.tvo-hd{display:flex;align-items:flex-start;gap:12px;margin-bottom:14px}
.tvo-hd b{display:block;font-family:var(--ti-font-display,'Bricolage Grotesque',sans-serif);
  font-size:17px;font-weight:800;letter-spacing:-.01em}
.tvo-hd span{display:block;font-size:12.5px;color:var(--ti-subtext);margin-top:2px}
.tvo-x{margin-left:auto;border:none;background:none;font-size:22px;line-height:1;
  color:var(--ti-faint);cursor:pointer;padding:0 4px}
.tvo-x:hover{color:var(--ti-text)}

/* Wraps, because eleven columns do not fit one line — and reading order is
   still left to right, top to bottom, which is the order of the table. */
.tvo-row{
  display:flex;flex-wrap:wrap;gap:8px;padding:14px;border-radius:14px;
  background:var(--ti-soft-fill);border:1px dashed var(--ti-border);
  touch-action:none;min-height:64px;align-content:flex-start}
.tvo-chip{
  display:inline-flex;align-items:center;gap:7px;background:#fff;
  border:1px solid var(--ti-border);border-radius:10px;padding:8px 12px;
  font-size:12.5px;font-weight:700;color:var(--ti-text);
  cursor:grab;user-select:none;touch-action:none;transition:box-shadow .12s,border-color .12s}
.tvo-chip i{color:var(--ti-faint);font-size:13px}
.tvo-chip:hover{border-color:var(--ti-primary)}
.tvo-chip.is-held{
  cursor:grabbing;border-color:var(--ti-primary);
  box-shadow:0 10px 22px -10px rgba(30,22,14,.5);position:relative;z-index:2}

.tvo-ft{display:flex;justify-content:flex-end;gap:9px;margin-top:15px}
.tvo-cancel,.tvo-go{
  border-radius:10px;padding:9px 16px;font-size:12.5px;font-weight:700;
  cursor:pointer;font-family:inherit}
.tvo-cancel{border:1px solid var(--ti-border);background:#fff;color:var(--ti-subtext)}
.tvo-cancel:hover{border-color:var(--ti-primary);color:var(--ti-primary)}
.tvo-go{border:none;background:var(--ti-primary);color:#fff}
.tvo-go:hover{filter:brightness(1.05)}

/* ==========================================================================
   ZEBRA STRIPING, EVERY TABLE IN THE PRODUCT. (Owner's call.)

   One plain row, one tinted, all the way down. On a leads table twenty columns
   wide the eye has to carry a row across a metre of screen, and a flat white
   field gives it nothing to hold on to — which is how you read the wrong
   person's phone number.

   Three levels that each read as different: white, the muted cream for the
   stripe, and the deeper soft fill for hover. #FDFBF8 was the first attempt and
   it was invisible — four units off white is not a stripe, it is a rounding
   error. Hover is re-declared BELOW the stripe so it still wins — the two rules
   carry identical specificity, so order is the only thing deciding it, and a
   hover you cannot see on every other row is worse than no stripe at all.
   ========================================================================== */
.ti-table tbody tr:nth-of-type(even) { background: var(--ti-muted-fill); }

.ti-table tbody tr:hover,
.ti-table tbody tr[onclick]:hover,
.ti-table tbody tr:nth-of-type(even):hover { background: var(--ti-soft-fill); }

/* The sticky first column has a background of its own — without this it stays
   white over a tinted row and the stripe stops dead at the second column. */
@media (max-width: 900px) {
  .ti-table-scroll .ti-table tbody tr:nth-of-type(even) td:first-child { background: var(--ti-muted-fill); }
  .ti-table-scroll .ti-table tbody tr:hover td:first-child { background: var(--ti-soft-fill); }
}

/* A group heading inside a searchable dropdown. Drawn only when the markup
   carries an <optgroup>, so it costs nothing on the ordinary lists. */
.ti-ss-group {
  padding: 9px 12px 5px; font-size: 10px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ti-faint); border-top: 1px solid var(--ti-border);
  margin-top: 4px;
}
.ti-ss-group:first-child { border-top: none; margin-top: 0; }

/* The read button, once pressed. */
.qb-capture-go:disabled { opacity: .6; cursor: progress; }

/* ---- Dashboard reminder calendar ------------------------------------------
   A month at a glance for the agent's own follow-ups. Deliberately small: it
   answers "where is the month heavy", not "what exactly is due", which is what
   My day is for — so a day is a number and a count, and clicking opens that
   day rather than trying to summarise it in a 30px box. */
.dsh-cal-head, .dsh-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.dsh-cal-head { margin-bottom: 5px; }
.dsh-cal-head span {
  text-align: center; font-size: 9.5px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ti-faint);
}
.dsh-cal-d {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  aspect-ratio: 1 / 1; border-radius: 9px; font-size: 12px; font-weight: 600;
  color: var(--ti-subtext); background: var(--ti-muted-fill); text-decoration: none;
}
.dsh-cal-d.is-out { opacity: .35; }
.dsh-cal-d.is-today { outline: 1.5px solid var(--ti-primary); outline-offset: -1.5px; font-weight: 800; }
.dsh-cal-d.has-work { background: var(--ti-brand-tint, #FFF1E8); color: var(--ti-primary); font-weight: 800; }
.dsh-cal-d.has-work:hover { background: #FFE3D2; }
.dsh-cal-d.has-work b {
  font-size: 9px; line-height: 1; margin-top: 1px; font-weight: 800;
  background: var(--ti-primary); color: #fff; border-radius: 999px; padding: 1px 4px;
}
.dsh-cal-nav {
  width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center;
  color: var(--ti-subtext); text-decoration: none; font-size: 11px; border: 1px solid var(--ti-border);
}
.dsh-cal-nav:hover { border-color: var(--ti-primary); color: var(--ti-primary); }
.dsh-cal-foot { margin-top: 10px; font-size: 11.5px; color: var(--ti-faint); text-align: center; }

/* ==========================================================================
   BOOTSTRAP DROPDOWN MENUS ON THE THEME'S TYPE SCALE. (Owner's call — "iski
   design font-size theme se sahi nahi dikh raha, same right side icon dropdown
   me bhi".)

   Same bug as the form-control block above, in a different control: a raw
   .dropdown-menu is Bootstrap's, so its items came out at the 1rem/16px default
   with 4px corners and a flat grey hover, hanging off a 38px chip whose own text
   is 13px. Beside the chrome around it that reads as a different typeface.

   The product already has a house menu — .ti-ss-panel, the searchable select —
   so these adopt ITS language rather than inventing a third one: 6px of panel
   padding, 8px item corners, 13.5px rows, soft-fill hover, brand-tint active.

   Scoped to .ti-shell (every menu in the workspace chrome — switcher, avatar,
   row actions) rather than one menu, because the mismatch was never specific to
   the switcher: it was every Bootstrap dropdown in the app.
   ========================================================================== */
.ti-shell .dropdown-menu {
  border: 1px solid var(--ti-border);
  border-radius: var(--ti-r-input);
  box-shadow: 0 18px 44px rgba(26,19,64,.18), 0 2px 6px rgba(26,19,64,.08);
  padding: 6px;
  font-size: 13.5px;
  color: var(--ti-text);
}
.ti-shell .dropdown-item {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 11px; border-radius: 8px;
  font-size: 13.5px; font-weight: 500; color: var(--ti-text);
}
/* The leading glyph is a label, not an actor — it stays quiet until the row is
   hovered, and holds a fixed column so the labels line up down the menu. */
.ti-shell .dropdown-item > i {
  font-size: 14px; width: 16px; flex-shrink: 0; text-align: center; color: var(--ti-faint);
}
.ti-shell .dropdown-item:hover,
.ti-shell .dropdown-item:focus { background: var(--ti-soft-fill); color: var(--ti-text); }
.ti-shell .dropdown-item:hover > i,
.ti-shell .dropdown-item:focus > i { color: var(--ti-primary); }
.ti-shell .dropdown-item:active,
.ti-shell .dropdown-item.active { background: var(--ti-brand-tint); color: var(--ti-primary); }
.ti-shell .dropdown-item:active > i,
.ti-shell .dropdown-item.active > i { color: var(--ti-primary); }
.ti-shell .dropdown-item-text { padding: 8px 11px; font-size: 13.5px; color: var(--ti-text); }
.ti-shell .dropdown-divider { margin: 5px 0; border-top-color: var(--ti-border); opacity: 1; }
/* Sign-out and switch-agency are POSTs, so their row is a <button> inside a
   <form>. Without this the form's own box breaks the row's full-bleed hover. */
.ti-shell .dropdown-menu form { margin: 0; }
.ti-shell .dropdown-menu form .dropdown-item { width: 100%; border: 0; background: none; font-family: inherit; text-align: left; }

/* An identity block at the head of a menu — who/where you are, not a link.
   Used by the agency switcher and the avatar menu so both read as one control. */
.ti-menu-id { padding: 9px 11px 10px; }
.ti-menu-id-title { font-weight: 700; font-size: 13.5px; color: var(--ti-text); line-height: 1.35; }
.ti-menu-id-sub { font-size: 11.5px; color: var(--ti-subtext); line-height: 1.4; margin-top: 1px; }
.ti-menu-id-meta { font-size: 11px; color: var(--ti-faint); line-height: 1.4; margin-top: 3px; }

/* ── Quick actions on a pipeline lead card ──────────────────────────────
   Call / WhatsApp / start a quotation, without opening the lead. The colour
   is set inline per action (blue, WhatsApp green, amber) so this carries only
   the shape and the states they all share. */
.ti-lead-act {
  width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; text-decoration: none; cursor: pointer;
  transition: transform .12s, filter .12s;
}
.ti-lead-act:hover { transform: translateY(-1px); filter: brightness(.96); }
.ti-lead-act:active { transform: none; }
/* No number on the lead: still legible, visibly not a button. Its title says
   why, so the answer is on the card rather than one click away. */
.ti-lead-act.is-off {
  background: var(--ti-muted-fill); color: var(--ti-faint);
  cursor: not-allowed; transform: none; filter: none;
}

/* ── A share menu has to escape the card it sits in ─────────────────────
   Same trap the searchable-select panel hit above: `.ti-card` carries
   `animation: cardLift .5s both`, and a filled animation keeps its final
   `transform: none` applied as the identity matrix — which still creates a
   stacking context. The menu's own z-index is then measured only against its
   siblings INSIDE that card, so the next card down the page paints over it and
   the reader sees just the first row.

   Lifting the whole card while the menu is open is the fix; 60 matches the
   z-index the menu itself asks for. .ti-share-menu.is-open is set by
   tiShareToggle — a stylesheet cannot read an inline display. */
.ti-card:has(.ti-share-menu.is-open),
.ti-lead-card:has(.ti-share-menu.is-open) { position: relative; z-index: 60; }

/* Same trap, same fix, for the Columns and Views menus: on Balance reminders the
   "Automatic reminders" and "Outstanding balances" cards painted straight over
   an open Columns list. [open] is the <details> element's own state. */
.ti-card:has(.ti-tbar-drop[open]) { position: relative; z-index: 60; }

/* An upload the browser refused before sending — see the guard in searchable.js. */
.ti-upload-err {
  display: flex; gap: 8px; align-items: flex-start;
  background: #FEF2F2; border: 1px solid #FECACA; color: #7F1D1D;
  border-radius: 11px; padding: 9px 12px; margin-top: 9px;
  font-size: 12.5px; line-height: 1.45;
  /* Whatever it lands beside, it gets a line to itself and the whole sentence
     is readable: it names the file, its size and the limit, and half of that is
     no use. `flex: 1 0 100%` claims the full row when the note is dropped into
     a flex container (the capture modal's file row is one, and there the note
     used to be squeezed to a few words beside the control); it is ignored
     outside a flex container, where a block is full-width anyway.
     `min-width: 0` lets the long filename wrap instead of forcing the row wide. */
  flex: 1 0 100%; min-width: 0; overflow-wrap: anywhere;
}
.ti-upload-err::before { content: "\F33A"; font-family: "bootstrap-icons"; flex-shrink: 0; }

/* agency-time.js — whose clock a reminder box is on, shown only when the
   browser's zone and the agency's differ. Information, not an error. */
.ti-agency-time {
  display: flex; gap: 6px; align-items: flex-start;
  margin: 6px 0 2px; font-size: 11.5px; line-height: 1.45; color: #92400E;
}
.ti-agency-time i { flex-shrink: 0; margin-top: 1px; }
/* A read-only note slot (agency-time.js) takes no room when the clocks agree. */
[data-agency-time]:not(input):empty { display: none; }

/* ── Traveller tier picker (<x-tier-pill>) — pin a tier by hand or back to auto ── */
.ti-tier-btn { border: 0; cursor: pointer; }
.ti-tier-btn:hover { filter: brightness(.94); }
.ti-tier-empty { background: transparent; color: var(--ti-faint); border: 1px dashed var(--ti-border); }
.ti-tier-menu { min-width: 250px; padding: 6px; font-size: 12.5px; }
.ti-tier-menu .dropdown-item { display: flex; align-items: center; gap: 9px; border-radius: 8px; padding: 7px 9px; white-space: normal; }
.ti-tier-menu .dropdown-item span { display: flex; flex-direction: column; }
.ti-tier-menu .dropdown-item small { color: var(--ti-faint); font-size: 11px; line-height: 1.35; }
.ti-tier-menu .dropdown-item.active, .ti-tier-menu .dropdown-item:active { background: color-mix(in srgb, var(--ti-primary) 12%, transparent); color: inherit; }
.ti-tier-menu-head { padding: 4px 9px 2px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ti-faint); }


/* ── Customers list: "Assigned to" cell picker ── */
.ti-assign-btn { border: 0; background: transparent; padding: 3px 6px; margin: -3px -6px; border-radius: 7px; font: inherit; color: inherit; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.ti-assign-btn:hover { background: color-mix(in srgb, var(--ti-primary) 10%, transparent); }
.ti-assign-btn.is-empty { color: var(--ti-faint); }
.ti-assign-btn.is-empty:hover { color: var(--ti-primary); }
.ti-assign-menu { min-width: 220px; max-height: 320px; overflow-y: auto; padding: 6px; font-size: 12.5px; }
.ti-assign-menu .dropdown-item { display: flex; align-items: center; gap: 8px; border-radius: 7px; padding: 6px 9px; }
.ti-assign-menu .dropdown-item.active, .ti-assign-menu .dropdown-item:active { background: color-mix(in srgb, var(--ti-primary) 12%, transparent); color: inherit; font-weight: 600; }
.ti-assign-search { padding: 2px 2px 6px; }
.ti-assign-search input { width: 100%; border: 1px solid var(--ti-border); border-radius: 8px; padding: 5px 9px; font-size: 12.5px; outline: none; }
.ti-assign-search input:focus { border-color: var(--ti-primary); }
.ti-assign-none { padding: 6px 9px; color: var(--ti-faint); }


/* A referral commission that cannot be paid until the customer has paid in
   full (ReferralCommission::payBlocker) — shown where "Mark paid" would be. */
.ti-com-lock { display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px; border-radius: 8px; background: #FFFBEB; border: 1px solid #FDE68A; color: #92400E; font-size: 11px; font-weight: 600; white-space: nowrap; }
.ti-com-lock i { color: #D97706; font-size: 10.5px; }
