/* building.One interactive layer v7.2 (shared by PM, Admin and Sales). Load AFTER /styles.css.
   v7.2: in-table skeleton rows (.ix-skel-tr), Admin/Sales pipeline skeleton (.ix-skel-board .lane / .ix-skel-opp).
   Rules: neutral elevation only (rgba black), focus = outline (never box-shadow), no glow/text-shadow/drop-shadow.
   Reuses styles.css tokens: --red --ink --muted --line --soft. New classes are prefixed .ix- */
:root{
  --ix-ease:cubic-bezier(0,0,.2,1);         /* ease-out */
  --ix-fast:120ms; --ix-med:150ms; --ix-slow:180ms;
  --ix-elev-1:0 1px 2px rgba(0,0,0,.06);
  --ix-elev-2:0 4px 12px rgba(0,0,0,.08);
  --ix-ring:var(--red);                      /* #eb202c: 4.4:1 on #fff, 4.06:1 on #f5f6f7 */
  --ix-ring-dark:#f09096;                    /* 7.45:1 on sidebar #191c1e */
  --ix-row-hover:#f7f8fa; --ix-row-press:#eef0f2;
  --ix-skel:#e7e9eb; --ix-skel-hi:#f0f1f3;   /* --line base; visible on #fff and --soft */
}

/* ---------- 1. Remove colored halos from styles.css ---------- */
.btn.primary{box-shadow:var(--ix-elev-1)}
.customer-stage-track .current span{box-shadow:none}
.board .lane.drop-target{box-shadow:none;outline:2px solid hsl(var(--lane-hue) 55% 45%);outline-offset:-2px}

/* ---------- 2. Hover + press (120-180ms ease-out) ---------- */
.btn,.icon-button,.nav-item,.tab,.card-move,.portal-go{
  transition:background-color var(--ix-med) var(--ix-ease),border-color var(--ix-med) var(--ix-ease),color var(--ix-med) var(--ix-ease),box-shadow var(--ix-med) var(--ix-ease),transform var(--ix-fast) var(--ix-ease)}
.btn:hover{filter:none;background-color:var(--soft);border-color:#dfe2e5}
.btn.primary:hover{background-color:#db2430;border-color:#db2430;color:#fff}
.btn:active:not(:disabled),.icon-button:active,.nav-item:active,.card-move:active,.portal-go:active{transform:scale(.98)}
.btn:disabled,.btn[aria-disabled=true]{transform:none;cursor:not-allowed}
.icon-button:hover{background-color:#f0f1f3}
.icon-button:active{background-color:#e5e7eb}
.tab:hover:not(.active){color:#4f575d}

/* Cards: 1px lift + neutral elevation; press settles */
.ops-project-card,.opportunity-card,.working-deal,.upcoming-appointment{
  transition:transform var(--ix-med) var(--ix-ease),box-shadow var(--ix-med) var(--ix-ease),border-color var(--ix-med) var(--ix-ease),opacity var(--ix-med) var(--ix-ease)}
.ops-project-card:hover,.opportunity-card:hover,.working-deal:hover{transform:translateY(-1px);box-shadow:var(--ix-elev-2)}
.ops-project-card:active,.opportunity-card:active,.working-deal:active{transform:translateY(0) scale(.99);box-shadow:var(--ix-elev-1)}
.ops-project-card.ix-dragging,.opportunity-card.ix-dragging{opacity:.55;transform:none;box-shadow:none}

/* Rows */
.table-click,.ops-list-row{transition:background-color var(--ix-fast) var(--ix-ease)}
.table-click:hover,.ops-list-row:hover{background-color:var(--ix-row-hover)}
.table-click:active,.ops-list-row:active{background-color:var(--ix-row-press)}
.table-click td:last-child svg,.ops-list-row>svg:last-child{transition:transform var(--ix-med) var(--ix-ease)}
.table-click:hover td:last-child svg,.table-click:focus-visible td:last-child svg{transform:translateX(2px)}

/* ---------- 3. Focus-visible: outline + offset, >=3:1, never removed ---------- */
button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible,[contenteditable]:focus-visible{
  outline:2px solid var(--ix-ring);outline-offset:2px;box-shadow:none}
.sidebar :focus-visible,.sidebar:focus-visible{outline-color:var(--ix-ring-dark)}
.table-click:focus-visible,.ops-list-row:focus-visible,.tab:focus-visible{outline-offset:-2px} /* parents clip (overflow) */
.field input:focus-visible,.field select:focus-visible,.field textarea:focus-visible{outline-offset:0;border-color:var(--red)}
.calendar-event:focus-visible,.working-deal:focus-visible{outline:2px solid var(--ix-ring);outline-offset:2px}
/* styles.css sets .global-search input{outline:none!important}; ring the wrapper instead so focus is never invisible */
.global-search{border-radius:6px}
.global-search:focus-within{outline:2px solid var(--ix-ring);outline-offset:4px}

/* ---------- 4. Customer cards as real <a> links ---------- */
a.ops-project-card,a.opportunity-card,a.ix-card-link{color:inherit;text-decoration:none;-webkit-user-drag:element;-webkit-tap-highlight-color:transparent}
a.ops-project-card:visited,a.opportunity-card:visited,a.ix-card-link:visited{color:inherit}
a.ops-project-card:hover,a.ops-project-card:focus,a.ix-card-link:hover{text-decoration:none}
a.ops-project-card[draggable=true]{cursor:grab;user-select:none}
a.ops-project-card[draggable=true]:active{cursor:grabbing}

/* ---------- 5. Panel / tab transitions (opacity+transform only: no layout jank) ---------- */
@keyframes ix-fade-in{from{opacity:0}to{opacity:1}}
@keyframes ix-drawer-in{from{transform:translateX(32px);opacity:0}to{transform:none;opacity:1}}
@keyframes ix-modal-in{from{transform:scale(.98);opacity:0}to{transform:none;opacity:1}}
@keyframes ix-panel-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
#overlay .scrim{animation:ix-fade-in var(--ix-slow) var(--ix-ease)}
#overlay .record-drawer{animation:ix-drawer-in var(--ix-slow) var(--ix-ease);will-change:transform}
#overlay .modal-wrap{animation:ix-fade-in var(--ix-med) var(--ix-ease)}
#overlay .modal{animation:ix-modal-in var(--ix-slow) var(--ix-ease)}
[role=tabpanel]{animation:ix-panel-in var(--ix-slow) var(--ix-ease)}
.ix-closing .record-drawer{transform:translateX(32px);opacity:0;transition:transform var(--ix-fast) var(--ix-ease),opacity var(--ix-fast) var(--ix-ease)}
.ix-closing .scrim,.ix-closing .modal-wrap{opacity:0;transition:opacity var(--ix-fast) var(--ix-ease)}

/* ---------- 6. Skeletons (replace "Loading…" text/spinners) ---------- */
@keyframes ix-shimmer{from{background-position:100% 0}to{background-position:-100% 0}}
.ix-skel{display:block;border-radius:5px;background:linear-gradient(90deg,var(--ix-skel) 0%,var(--ix-skel-hi) 50%,var(--ix-skel) 100%) 0 0/200% 100%;animation:ix-shimmer 1.4s linear infinite}
.ix-skel-line{height:10px;margin:6px 0}
.ix-skel-line.sm{height:8px}.ix-skel-line.lg{height:16px}
.ix-w-30{width:30%}.ix-w-45{width:45%}.ix-w-60{width:60%}.ix-w-80{width:80%}.ix-w-100{width:100%}
.ix-skel-card{padding:12px 10px;margin-bottom:8px;border:1px solid #e6e7ea;border-radius:11px;background:#fff}
.ix-skel-card .ix-skel-row{display:flex;justify-content:space-between;gap:10px}
.ix-skel-lane .ix-skel-card{box-sizing:border-box;min-height:128px} /* = a real .ops-project-card (4 text lines + chip), so lanes do not jump */
.ix-skel-table{width:100%;border-collapse:collapse}
.ix-skel-table td{padding:16px;border-top:1px solid #f0f1f3}
.ix-skel-wrap .ix-skel-tr td{vertical-align:middle} /* real th/td metrics come from the app's table styles */
.ix-skel-tr td:first-child .ix-skel-line:first-child{margin-top:3px} /* 3+10+6+8+6 = 33px = .customer-list-name, so a row is 68px like the real row */
.ix-skel-board .lane{background:#edeff1;border-color:#e3e6e9} /* neutral: no stage hue while loading */
.ix-skel-board .lane-head{position:static}
.ix-skel-opp .opportunity-card{cursor:progress}
.ix-skel-opp{box-sizing:border-box;min-height:186px} /* = a real .opportunity-wrap (card + Move bar) */
.ix-skel-opp .ix-skel-row{display:flex;justify-content:space-between;gap:10px;margin-top:10px}
.ix-skel-drawer{padding:4px 0}
.ix-skel-drawer .ix-skel-actions{display:flex;gap:8px;margin:18px 0 24px}
.ix-skel-drawer .ix-skel-actions .ix-skel{height:34px;width:96px;border-radius:6px}
.ix-skel-block{height:72px;border-radius:9px;margin:12px 0}
.ix-skel-file .ix-skel-banner{height:96px;border-radius:13px;margin-bottom:16px}
.ix-skel-file .ix-skel-grid{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:16px}
.ix-skel-file .ix-skel-tabs{display:flex;gap:20px;margin:6px 0 18px}
.ix-skel-file .ix-skel-tabs .ix-skel{height:10px;width:64px}
@media(max-width:800px){.ix-skel-file .ix-skel-grid{grid-template-columns:1fr}}
[aria-busy=true]{cursor:progress}
.ix-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---------- 7. Inline-edit affordance (hook: [data-ix-edit]) ---------- */
[data-ix-edit]{display:inline-block;max-width:100%;cursor:text;border-radius:4px;padding:1px 22px 1px 3px;margin:-1px -3px;position:relative;
  background-image:linear-gradient(currentColor,currentColor);background-size:0 1px;background-repeat:no-repeat;background-position:3px calc(100% - 1px);
  transition:background-color var(--ix-fast) var(--ix-ease),background-size var(--ix-med) var(--ix-ease)}
[data-ix-edit]::after{content:"";position:absolute;right:4px;top:50%;width:12px;height:12px;margin-top:-6px;opacity:0;background:var(--muted);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z'/%3E%3C/svg%3E") center/contain no-repeat;
  transition:opacity var(--ix-fast) var(--ix-ease)}
[data-ix-edit]:hover,[data-ix-edit]:focus-visible{background-color:var(--soft);background-size:calc(100% - 25px) 1px}
[data-ix-edit]:hover::after,[data-ix-edit]:focus-visible::after{opacity:1}
[data-ix-edit]:focus-visible{outline:2px solid var(--ix-ring);outline-offset:1px}
[data-ix-edit][aria-disabled=true]{cursor:default;background:none}
[data-ix-edit][aria-disabled=true]::after{display:none}
@media(hover:none),(pointer:coarse){[data-ix-edit]::after{opacity:.7}}

/* ---------- 8. Row quick actions (hook: .ix-row-actions inside a row) ---------- */
.ix-row-actions{display:inline-flex;gap:4px;justify-content:flex-end;opacity:0;transition:opacity var(--ix-med) var(--ix-ease)}
.ix-row-actions .icon-button,.ix-row-actions .btn{padding:6px 8px}
.table-click:hover .ix-row-actions,.table-click:focus-within .ix-row-actions,
.ops-list-row:hover .ix-row-actions,.ops-list-row:focus-within .ix-row-actions,
.ix-row:hover .ix-row-actions,.ix-row:focus-within .ix-row-actions,
.ops-project-card:hover .ix-row-actions,.ops-project-card:focus-within .ix-row-actions,
.ix-row-actions:focus-within{opacity:1}
@media(hover:none),(pointer:coarse){.ix-row-actions{opacity:1}}

/* ---------- 9. Forge v7 state contract ---------- */
/* 9a. Per-record save: .ix-record[data-state=saving|saved|retrying|failed|conflict|queued].
   interactive.js injects .ix-save (icon + text [+ Retry/Review buttons]). Timing is pure CSS. */
@keyframes ix-appear{from{opacity:0}to{opacity:1}}
@keyframes ix-saved-out{0%,90%{opacity:1}100%{opacity:0;visibility:hidden}}
@keyframes ix-pulse{0%,100%{opacity:.35}50%{opacity:1}}
.ix-save{display:none;align-items:center;gap:6px;min-height:20px;font-size:11px;font-weight:600;line-height:1.3;color:#626970;vertical-align:middle}
.ix-record[data-state] .ix-save{display:inline-flex}
.ix-record .ix-record:not([data-state]) .ix-save{display:none}
.ix-save-icon{flex:none;width:12px;height:12px;border-radius:50%;background:#a0a6ad}
.ix-save-btn{display:none;font:inherit;font-weight:700;color:inherit;text-decoration:underline;text-underline-offset:2px;padding:2px 4px;margin-left:-2px;border-radius:4px;position:relative;z-index:2}
.ix-save-btn:hover{background:var(--soft)}
.ix-save-btn{min-height:24px;min-width:32px} /* WCAG 2.5.8 minimum */
@media (pointer:coarse){.ix-save-btn{min-height:32px;min-width:44px;margin-block:-4px}}
/* saving: shown only if still pending at 150ms */
.ix-record[data-state=saving] .ix-save{animation:ix-appear 1ms linear 150ms both}
.ix-record[data-state=saving] .ix-save-icon,.ix-record[data-state=retrying] .ix-save-icon{width:6px;height:6px;margin:3px;animation:ix-pulse 1.2s ease-in-out infinite}
.ix-record[data-state=saving],.ix-record[data-state=retrying]{cursor:progress}
/* saved: check, holds 2s then fades */
.ix-record[data-state=saved] .ix-save{animation:ix-saved-out 2.2s linear forwards}
.ix-record[data-state=saved] .ix-save-icon{background:#3c8b68;-webkit-mask:var(--ix-check) center/10px no-repeat;mask:var(--ix-check) center/10px no-repeat;border-radius:0}
/* failed: persists; red text (#c62330 = .error-text) + Retry */
.ix-record[data-state=failed] .ix-save{color:#c62330}
.ix-record[data-state=failed] .ix-save-icon,.ix-record[data-state=conflict] .ix-save-icon{background:currentColor;-webkit-mask:var(--ix-alert) center/12px no-repeat;mask:var(--ix-alert) center/12px no-repeat;border-radius:0}
.ix-record[data-state=failed] .ix-retry{display:inline-block}
.ix-record[data-state=failed] .ix-retry:hover{background:#fff0f0}
/* conflict: persists; amber (#ba8739 = .badge.orange) + Review */
.ix-record[data-state=conflict] .ix-save{color:#8a6528}
.ix-record[data-state=conflict] .ix-review{display:inline-block}
.ix-record[data-state=conflict] .ix-review:hover{background:#fcf5e7}
/* queued: persists; neutral, hollow dot */
.ix-record[data-state=queued] .ix-save-icon{width:8px;height:8px;margin:2px;background:none;border:1.5px solid #8a949c}
/* record borders: neutral colour change only, never a halo */
.ix-record[data-state=failed]>.ops-project-card,.ops-project-card.ix-record[data-state=failed],.ix-record[data-state=failed]>.opportunity-card{border-color:#cf3b45}
.ix-record[data-state=conflict]>.ops-project-card,.ops-project-card.ix-record[data-state=conflict]{border-color:#ba8739}
tr.ix-record[data-state=failed]>td:first-child,tr.ix-record[data-state=conflict]>td:first-child{background-image:linear-gradient(var(--ix-rail),var(--ix-rail));background-size:2px 100%;background-repeat:no-repeat}
tr.ix-record[data-state=failed]{--ix-rail:#cf3b45}
tr.ix-record[data-state=conflict]{--ix-rail:#ba8739}
form.ix-record .ix-save{margin-left:10px}
.ix-queue .ix-record[data-state=failed],.ix-queue .ix-record[data-state=conflict]{border-color:#e5e9ec;background:#fff}
.ix-queue .ix-record[data-state=failed]{border-color:#cf3b45}
.ix-queue .ix-record[data-state=conflict]{border-color:#ba8739}
tr.ix-record[data-state]>td:first-child>.ix-save{display:flex;margin-top:6px;white-space:normal}
.ix-card{position:relative;margin-bottom:8px}
.ix-card>.ops-project-card{margin-bottom:0}
.ix-card>.ix-save{padding:4px 2px 0}
:root{
  --ix-check:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  --ix-alert:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7.5v6M12 16.5v.5'/%3E%3C/svg%3E")}

/* 9b. Sync indicator: <span class="ix-sync" role="status" data-state="loading|updating|synced" [data-error=true]>Forge text</span>
   Forge's styles.css (c2448b6) sets the base. This adds the state dot and raises text contrast:
   Forge's #7b848c is 3.8:1 and its #9aa1a8 (updating/loading) is 2.6:1 at 10px; #626970 is 5.56:1. */
.ix-sync{display:inline-flex;align-items:center;gap:7px;font-size:10px;font-weight:600}
.ix-sync[data-state][data-state]{color:#626970}
.ix-sync[data-error=true][data-state]{color:#c62330}
.ix-sync::before{content:"";width:6px;height:6px;border-radius:50%;background:#a0a6ad;flex:none}
.ix-sync[data-state=loading]::before,.ix-sync[data-state=updating]::before{animation:ix-pulse 1.2s ease-in-out infinite}
.ix-sync[data-state=synced]::before{background:#3c8b68}
.ix-sync[data-error=true]::before{background:#c62330}
.ix-sync:empty{display:none}
@media(max-width:500px){.ix-sync{font-size:0;gap:0}} /* dot only on phones; text stays in the a11y tree */

/* 9c. Skeleton containers (contract: aria-busy + data-ix-skeleton) */
[aria-busy=true][data-ix-skeleton]{cursor:progress}
[data-ix-skeleton=table]{overflow:hidden}

/* 9d. Draft restored: styled by Forge's styles.css (.ix-draft-note, c30162a). Only the focus ring and touch target are added here. */
.ix-draft-note .ix-draft-discard{min-height:28px}

/* 9e. Link rows/cards with sibling actions (Forge: stretched a.row-link::after; call/text/email are siblings) */
.customer-row:focus-within{background-color:var(--ix-row-hover)}
tr.table-click:active,a.ops-list-row:active{background-color:var(--ix-row-press)} /* after focus-within: the stretched link takes focus on mousedown */
.customer-row td :is(button,a:not(.row-link),.ix-row-actions,.ix-save),.ix-card .ix-card-actions{position:relative;z-index:1}
.ix-card .ix-card-actions{position:absolute;right:8px;bottom:8px;display:inline-flex;gap:4px;opacity:0;transition:opacity var(--ix-med) var(--ix-ease)}
.ix-card:hover .ix-card-actions,.ix-card:focus-within .ix-card-actions{opacity:1}
.ix-card .ix-card-actions .icon-button{background:#fff;border:1px solid #e6e7ea;padding:5px}
@media(hover:none),(pointer:coarse){.ix-card .ix-card-actions{opacity:1}}
.ops-list-row:focus-visible{outline-offset:-2px}

/* ---------- 10. Empty states with a next action ---------- */
.empty .ix-empty-title,.ops-empty .ix-empty-title{display:block;font-weight:700;color:#3f474d;font-size:12px;margin-bottom:4px}
.empty .ix-empty-action,.ops-empty .ix-empty-action,#ops-pipeline-no-results .ix-empty-action{margin-top:12px}
.ops-empty{border:1px dashed #dfe2e5;border-radius:11px;margin:2px 0 8px;line-height:1.5}
.ops-lane.drop-allowed .ops-empty{border-color:#a0a6ad}

/* ---------- 11. Reduced motion: no transforms, transitions or shimmer ---------- */
@media(prefers-reduced-motion:reduce){
  #app *,#app *::before,#app *::after,#overlay *,#overlay *::before,#overlay *::after,#toast,.sidebar{
    transition:none!important;animation:none!important}
  .btn:active,.icon-button:active,.nav-item:active,.card-move:active,.portal-go:active,
  .ops-project-card:hover,.ops-project-card:active,.opportunity-card:hover,.opportunity-card:active,
  .working-deal:hover,.working-deal:active,.table-click:hover td:last-child svg{transform:none}
  .ix-skel{background:var(--ix-skel)}
  :is(#app,#overlay) .ix-record[data-state=saving] .ix-save{animation:none!important;opacity:1}
  /* Saved still clears at 2s, as an instant step with no fade */
  :is(#app,#overlay) .ix-record[data-state=saved] .ix-save{animation:ix-saved-hide 2s steps(1,end) forwards!important}
}
@keyframes ix-saved-hide{to{visibility:hidden}}
