/* ui/integrations.css — owned by W6. Every selector .ig-* prefixed (SHELL_CONTRACT §3.2).

   ANDREW, ON THE LIVE PAGE: "We don't need to explain everything. There's so many words.
   We don't need to tell them we know they use Humanforce for example. Just the subtle hint
   that it's connected is enough! Where are the vendor logos.... The page must be sleek.
   Simple."

   He is right, and the page I shipped was arguing with the customer instead of showing him
   something. So: the LOGO does the work, the green tick IS the moment, and the words are
   gone. The evidence is not deleted — it moved to the detail panel, where a CEO who asks
   "how do you know?" finds it in one click. Discoverable, not declaimed.

   GEOMETRY IS LIFTED FROM THE CAPTURE OF LOOP'S REAL PAGE (01_INTEGRATIONS.md §4) —
   measured computed styles, not eyeballed:
     card    #FFF · 0.67px solid #E5E7EB · 12px radius · 24px padding · no shadow
     grid    3 × 387px · 24px gap
     stack   logo (centred) -> name + state pill -> one line -> action
     pills   9999px · 12px/500 · 2px 8px
     primary #271257 filled · 48px tall · 48px radius · 14px/600 · full width
     Manage  bare text link · #581C87 · 14px/600
   Match the chrome. Beat the substance. */

/* THE VARIABLES MUST BE DEFINED ON *BOTH* ROOTS, AND THIS IS NOT A TIDINESS POINT.

   The detail panel is PORTALLED TO document.body — it is appended outside .ig-wrap so it
   can sit above everything. CSS custom properties inherit down the DOM tree, so a panel
   that is not a descendant of .ig-wrap resolves every var() to NOTHING.

   What that actually produced: `.ig-btn.primary { background:var(--ig-depth); color:#FFF }`
   became `background: rgba(0,0,0,0); color:#FFF` — WHITE TEXT ON A WHITE PANEL. The
   "Test connection" button was fully present, 157px wide, visibility:visible, and
   completely invisible to a human being. `Save changes` lost its purple and went black.
   The entire panel had been silently unstyled and it looked *almost* fine, which is why
   nobody caught it.

   This is the same bug v9.84 shipped a fix for ("Update integration has been an INVISIBLE
   BUTTON this whole time") — that fix treated the symptom on one button. This is the
   cause, and it was going to keep producing new invisible buttons forever.

   Gated below, and red-proofed. */
.ig-wrap, .ig-detail {
  --ig-indigo:#4330F5; --ig-depth:#271257; --ig-deep:#1A0B3D; --ig-manage:#581C87;
  --ig-line:#E5E7EB; --ig-muted:#6B7280; --ig-ink:#111827;
  --ig-green-bg:rgb(241,252,243); --ig-green-fg:rgb(30,119,53);
  --ig-amber-bg:rgb(255,251,235); --ig-amber-fg:rgb(180,83,9);
  font-family:Poppins,system-ui,sans-serif; color:var(--ig-ink);
}

/* ---------- header: two lines, then get out of the way ---------- */
.ig-head { display:flex; justify-content:space-between; align-items:flex-end; gap:24px;
           flex-wrap:wrap; margin-bottom:8px; }
.ig-tenancy { font-size:11px; font-weight:600; letter-spacing:.5px; text-transform:uppercase;
              color:var(--ig-indigo); margin:0 0 6px; }
.ig-h1 { font-family:var(--font-head, 'Sansation', 'Poppins', sans-serif); font-size:26px; font-weight:700; margin:0;
         letter-spacing:-.2px; }
.ig-sub { color:var(--ig-muted); font-size:14px; margin:6px 0 0; }

.ig-counts { display:flex; gap:20px; padding-bottom:2px; }
.ig-count b { font-family:var(--font-head, 'Sansation', 'Poppins', sans-serif); font-size:20px; font-weight:700;
              margin-right:6px; }
.ig-count { font-size:12px; color:var(--ig-muted); white-space:nowrap; }

/* ---------- category: heading only. The description paragraphs are gone. ---------- */
.ig-cat { margin-top:36px; }
.ig-cat-h { font-size:12px; font-weight:600; letter-spacing:.6px; text-transform:uppercase;
            color:var(--ig-muted); margin:0 0 16px; }

.ig-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,387px)); gap:24px; }

/* ---------- the card ---------- */
.ig-card { background:#FFF; border:0.67px solid var(--ig-line); border-radius:12px;
           padding:24px; display:flex; flex-direction:column; align-items:center;
           text-align:center; box-shadow:none; }

/* MANDATORY must not look like a box someone happened to tick. One hairline of indigo. */
.ig-card.is-mandatory { border-color:#D6CFFF; }

/* The unsupported tier gets a dashed edge so it can never be skim-read as a connection —
   the distinction has to survive a glance from four feet away. */
.ig-card.is-unsup { border-style:dashed; background:#FCFCFD; }

/* ---------- THE LOGO. It is the whole visual. ---------- */
/* THE REAL MARKS NEED THE ROOM, AND THE OLD PLATE HAS TO GO. W21 found both of these by
   LOOKING AT THE PAGE, and no gate saw either; I re-confirmed both before taking them.

   background MUST be stated. styles.css STILL carries W6's stale inlined copy of the ig-*
   rules (the two-copies problem from the W6 handover, still live) and its .ig-logo paints
   a lavender plate: `.ig-logo { background:#F3F0FF; width:44px; height:44px; }`. This
   file loads after it and wins on the properties it SETS -- but only on those. Leave
   background unset and that plate shows through behind every real vendor logo, which is
   exactly what it did: nine trademarks each sitting on a lilac chip.

   And the sizing: W6's marks were 48x48 tiles it drew itself, so a 48px box was right for
   them. The real marks are WORDMARKS -- "employment hero" is ~4:1 -- and a wordmark
   crushed into a 48px square renders as an illegible smudge. Every mark in ui/logos.js is
   composed onto one 200x56 canvas and optically sized by aspect (wordmark 30px tall,
   lockup 40px, square glyph 48px) so they share a baseline instead of one dwarfing the
   next. The box has to match the canvas.

   W6's three surviving tiles (proda, dept_health, manad) are viewBox="0 0 48 48" with no
   preserveAspectRatio override, so they letterbox to 56x56 centred in the 200x56 box and
   keep their square. Verified on the screen, not assumed. */
.ig-logo { width:200px; height:56px; margin:0 auto 16px; display:flex; align-items:center;
           justify-content:center; background:transparent; border-radius:0; flex:none; }
.ig-logo svg, .ig-logo img { width:200px; height:56px; display:block; }
/* The monogram is the SAFETY NET and stays square — a 200x56 pair of initials floating in
   a letterbox reads as a bug, not a fallback. */
.ig-logo.is-mono { width:56px; height:56px; border-radius:12px; overflow:hidden;
                   font-family:var(--font-head, 'Sansation', 'Poppins', sans-serif); font-weight:700; font-size:17px;
                   letter-spacing:-.3px; }
.ig-card.is-unsup .ig-logo { filter:grayscale(1); opacity:.62; }

.ig-card-top { display:flex; align-items:center; justify-content:center; gap:8px;
               flex-wrap:wrap; margin-bottom:8px; }
.ig-name { font-family:var(--font-head, 'Sansation', 'Poppins', sans-serif); font-weight:600; font-size:16px; margin:0; }

/* ONE LINE. Gated at 90 characters on the server. */
.ig-powers { font-size:13px; line-height:1.5; color:var(--ig-muted); margin:0 0 20px;
             min-height:39px; }

/* ---------- data-available badge (WGS-124) ----------
   A quiet green "● Data available" below the powers line on every connected,
   always_on and mandatory card. Consistent with the config-window pattern
   (qic-q-avail). Available cards carry no badge — the "Connect" button is
   their signal. Unsupported cards get no badge either. */
.ig-data-badge { display:inline-block; font-size:11px; font-weight:600;
                 color:var(--ig-green-fg); background:var(--ig-green-bg);
                 border-radius:9999px; padding:2px 10px; margin:0 0 10px;
                 white-space:nowrap; line-height:1.6; }

/* ---------- the volume line (W106) ----------
   A count and a timestamp, derived from the one pull producer. Today it reads
   "— entries · Last pull: never" on every card, because Junior has no live pulls —
   that is the fact, quietly stated, not a defect badge. */
.ig-vol { display:flex; justify-content:space-between; gap:8px; font-size:11.5px;
          color:var(--ig-muted); margin:-4px 0 14px; cursor:help;
          font-variant-numeric:tabular-nums; }
.ig-vol b { font-weight:600; color:inherit; }
/* W107 — a SIMULATED volume line (demo controller, volumes ON). The line already says
   "demo" in text and carries its generated provenance on hover; the italic is just the
   quiet visual echo of that word, not the disclosure itself. */
.ig-vol.ig-vol-demo { font-style: italic; }
/* W107 — a card above the demo controller's dialled tier. Greyed; its own plan badge
   (Pro / Premium, read from pricing) is the whole statement of what unlocks it. */
.ig-card.ig-demo-locked { opacity: .55; }
.ig-card.ig-demo-locked .ig-plan { opacity: 1; font-weight: 700; }

/* ---------- the plan badge ----------
   Which tier a vendor belongs to. Quiet on purpose: the state pill above it answers "is this
   connected", which is the question a CIO opened the page with. The plan answers "what does it
   cost", which is a different conversation and must not shout over the first one.

   There is no locked/denied variant, and that is deliberate. Andrew's word was "prepare" to
   start locking clients in and out. A padlock here would imply a gate that does not exist.
   (W107's .ig-demo-locked above is NOT that variant: it is the demo bar's "view as — tier"
   preview, painted by the controller Andrew drives, and it claims nothing about the server.) */
.ig-plan { display:inline-block; font-size:11px; font-weight:600; letter-spacing:.02em;
           padding:2px 8px; border-radius:9999px; margin:0 0 10px; line-height:1.5;
           background:#F3F4F6; color:#4B5563; }
/* Free forever is the one that carries colour: it is the promise, and it is the only badge on
   the page a buyer can act on without talking to us. */
.ig-plan-free { background:var(--ig-green-bg, #F1FCF3); color:var(--ig-green-fg, #1E7735); }
.ig-plan-pro { background:#EEEBFF; color:var(--ig-depth, #271257); }
.ig-plan-premium { background:var(--ig-depth, #271257); color:#FFF; }

/* ---------- state pills ---------- */
.ig-pill { display:inline-flex; align-items:center; gap:4px; font-size:12px; font-weight:500;
           padding:2px 8px; border-radius:9999px; white-space:nowrap; line-height:1.5; }
.ig-pill.connected { background:var(--ig-green-bg); color:var(--ig-green-fg); }
.ig-pill.mandatory { background:#EEEBFF; color:var(--ig-depth); }
/* AVAILABLE is an OFFER, not a defect — see the note in integrations.js. Neutral, not amber. */
.ig-pill.available { background:#F3F4F6; color:#4B5563; }
/* Amber is spent on the one thing that warrants attention: a system we do NOT integrate with. */
.ig-pill.unsup { background:var(--ig-amber-bg); color:var(--ig-amber-fg); }

/* ---------- buttons ---------- */
.ig-btn { height:48px; border-radius:48px; font-weight:600; font-size:14px; cursor:pointer;
          font-family:Poppins,sans-serif; width:100%; border:0; margin-top:auto; }
.ig-btn.primary { background:var(--ig-depth); color:#FFF; }
.ig-btn.primary:hover { background:var(--ig-indigo); }
.ig-btn.manage { background:#FFF; color:var(--ig-manage); }
.ig-btn.manage:hover { text-decoration:underline; }
.ig-btn.request { background:#FFF; color:var(--ig-depth); border:1px solid var(--ig-line); }
.ig-btn.request:hover { border-color:var(--ig-depth); }

/* DESTRUCTIVE ACTIONS DO NOT GET PRIMARY WEIGHT. Loop styles `Remove integration` as a
   filled dark-purple pill, identical in weight to `Update integration`. */
.ig-btn.danger { background:#FFF; color:#B42318; border:1px solid #FDA29B; width:auto;
                 padding:0 16px; height:40px; }
.ig-btn.danger:hover { background:#FEF3F2; }
.ig-btn[disabled] { opacity:.5; cursor:not-allowed; }

/* ---------- detail panel ---------- */
.ig-detail { position:fixed; inset:0; background:rgba(26,11,61,.45); display:flex;
             justify-content:flex-end; z-index:900; }
.ig-panel { background:#FFF; width:min(560px,100%); height:100%; overflow-y:auto; padding:28px;
            font-family:Poppins,sans-serif; }
.ig-panel-top { display:flex; align-items:center; gap:14px; margin:14px 0 4px; }
.ig-panel h2 { font-family:var(--font-head, 'Sansation', 'Poppins', sans-serif); margin:0; font-size:22px; }
.ig-back { background:none; border:0; color:var(--ig-manage); font-weight:600; font-size:14px;
           cursor:pointer; padding:0; font-family:Poppins,sans-serif; }

.ig-rows { border:0.67px solid var(--ig-line); border-radius:12px; margin:20px 0; }
.ig-row { display:flex; justify-content:space-between; gap:16px; padding:12px 16px;
          border-bottom:0.67px solid var(--ig-line); font-size:13px; align-items:center; }
.ig-row:last-child { border-bottom:0; }
.ig-row dt { color:var(--ig-muted); margin:0; flex:none; }
.ig-row dd { margin:0; text-align:right; font-weight:500; }

/* THE EVIDENCE. Cut from the card, kept here. "How do you know we're on Humanforce?" */
.ig-why { font-size:13px; line-height:1.55; color:var(--ig-green-fg); background:var(--ig-green-bg);
          border-radius:10px; padding:12px 14px; margin:0 0 4px; }
.ig-why b { font-weight:600; }
.ig-signal { font-size:13px; line-height:1.55; color:var(--ig-amber-fg);
             background:var(--ig-amber-bg); border-radius:10px; padding:12px 14px; margin:0; }

/* I4: absence is not a value. Visibly different from a real one — never a blank, never a 0,
   and never Loop's `Invalid Date`. */
.ig-nodata { font-size:12px; color:var(--ig-muted); font-style:italic; }
.ig-nodata b { font-style:normal; font-weight:600; color:#4B5563; }

/* ---------- connection panel (credentials never leave the page) ---------- */
.ig-conn { border:0.67px solid var(--ig-line); border-radius:12px; padding:20px; margin:20px 0; }
.ig-conn-head { display:flex; justify-content:space-between; align-items:center; gap:12px;
                margin-bottom:6px; }
.ig-conn-head h3 { margin:0; font-size:15px; font-family:var(--font-head, 'Sansation', 'Poppins', sans-serif); }
.ig-conn-kind { font-size:11px; font-weight:600; color:var(--ig-depth); background:#EEEBFF;
                padding:2px 8px; border-radius:9999px; }
.ig-conn-blurb { font-size:13px; line-height:1.55; color:#374151; margin:0 0 16px; }
/* HL-125 — instances. The count pill on the card; the add row under the panels. */
.ig-inst-n { font-size:11px; font-weight:600; color:var(--ig-muted); background:#F3F4F6;
             padding:2px 8px; border-radius:9999px; }
.ig-conn-head .ig-btn.danger { margin-left:auto; }
.ig-inst-add { margin-top:14px; }
.ig-f-grid { display:grid; gap:14px; }
.ig-f label { display:block; font-size:12px; font-weight:600; color:#374151; margin-bottom:4px; }
.ig-f-wrap { display:flex; gap:8px; }
.ig-f-in { flex:1; height:40px; border:1px solid var(--ig-line); border-radius:8px;
           padding:0 12px; font-size:13px; font-family:ui-monospace,monospace; min-width:0; }
.ig-f-in:focus { outline:2px solid var(--ig-indigo); outline-offset:-1px; border-color:transparent; }
.ig-f-ro { font-size:13px; padding:9px 12px; background:#F9FAFB; border:1px solid var(--ig-line);
           border-radius:8px; font-family:ui-monospace,monospace; }
.ig-f-eye { border:1px solid var(--ig-line); background:#FFF; border-radius:8px; padding:0 12px;
            font-size:12px; font-weight:600; cursor:pointer; color:var(--ig-manage); }
.ig-f-hint { font-size:11px; color:var(--ig-muted); margin:4px 0 0; }
.ig-conn-acts { display:flex; gap:12px; margin-top:18px; }
.ig-conn-acts .ig-btn { width:auto; padding:0 22px; height:44px; margin-top:0; }
.ig-conn-result { font-size:13px; margin-top:14px; display:none; align-items:center; gap:8px; }
.ig-conn-result.is-busy, .ig-conn-result.is-ok { display:flex; }
.ig-conn-result.is-ok { color:var(--ig-green-fg); background:var(--ig-green-bg);
                        padding:10px 12px; border-radius:8px; }
.ig-conn-result.is-busy { color:var(--ig-muted); }
.ig-conn-sim { margin-top:12px; }

.ig-actions { display:flex; gap:12px; flex-wrap:wrap; align-items:center; margin-top:8px; }
.ig-actions .ig-btn:not(.danger) { width:auto; padding:0 24px; margin-top:0; }

/* ---------- what we cannot see: one tight line each ---------- */
.ig-gaps { margin-top:40px; border-top:0.67px solid var(--ig-line); padding-top:24px; }
.ig-gap { font-size:13px; color:#374151; line-height:1.6; margin:0 0 8px; padding-left:12px;
          border-left:2px solid #FCA5A5; }
.ig-gap.unsupported_system { border-left-color:var(--ig-amber-fg); }
.ig-gap b { font-weight:600; color:var(--ig-ink); }

.ig-weak { margin-top:16px; font-size:12px; color:var(--ig-muted); line-height:1.6; }
.ig-weak summary { cursor:pointer; }

/* ---------- error boundary: Loop's clean layout, NOT their leaked stack trace ---------- */
.ig-err { text-align:center; padding:48px 24px; }
.ig-code { font-family:ui-monospace,monospace; font-size:12px; color:var(--ig-muted);
           background:#F9FAFB; border:0.67px solid var(--ig-line); border-radius:8px;
           padding:8px 12px; display:inline-block; margin-top:12px; }

@media (max-width:880px){ .ig-grid { grid-template-columns:1fr; } }


/* ---- SELF-MANAGE: scope -> map -> monitoring ------------------------------------
   Every selector is .ig-sm* — inside this file's existing .ig- namespace, so
   gate_css_namespace stays green and nothing here can leak into another module.
   TOKENS, NEVER HEXES: --ig-depth is Russian Violet #271257, the anchor. --ig-indigo
   (#4330F5) is demoted and is not used below.                                      */
.ig-sm { margin-top: 22px; border-top: 1px solid var(--ig-line); padding-top: 18px; }

.ig-sm-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin: 18px 0 6px; flex-wrap: wrap; }
.ig-sm-head h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--ig-ink); }
.ig-sm-ro { font-size: 12px; color: var(--ig-muted); text-align: right; max-width: 62%; }
.ig-sm-line { margin: 0 0 10px; font-size: 12.5px; color: var(--ig-ink); }

.ig-sm-t { width: 100%; border-collapse: collapse; font-size: 12.5px; margin: 6px 0 4px; }
.ig-sm-t th { text-align: left; font-weight: 600; color: var(--ig-muted); font-size: 11px;
  text-transform: uppercase; letter-spacing: .04em; padding: 6px 8px;
  border-bottom: 1px solid var(--ig-line); }
.ig-sm-t td { padding: 8px; border-bottom: 1px solid var(--ig-line);
  vertical-align: top; color: var(--ig-ink); }
.ig-sm-t code { font-size: 11px; color: var(--ig-muted); word-break: break-all; }
.ig-sm-t tr.is-off td { opacity: .62; }
.ig-sm-t tr.is-open td { background: var(--ig-amber-bg); }

.ig-sm-sub { margin: 3px 0 0; font-size: 11.5px; color: var(--ig-muted); line-height: 1.45; }
.ig-sm-n { font-size: 11px; color: var(--ig-muted); }

.ig-sm-pill { display: inline-block; border-radius: 999px; padding: 1px 8px;
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }
.ig-sm-pill.on { background: var(--ig-green-bg); color: var(--ig-green-fg); }
.ig-sm-pill.off { background: #F3F4F6; color: var(--ig-muted); }

/* "Needs your answer" is a DESIGNED state, not a blank. The hard half of pre-fill is
   not pre-filling a row we cannot infer — so the row that we could not infer has to
   look like a question, not like an empty cell somebody forgot. */
.ig-sm-open { color: var(--ig-amber-fg); font-weight: 600; }
.ig-sm-blocks { margin: 8px 0 0; font-size: 12px; color: var(--ig-amber-fg);
  background: var(--ig-amber-bg); border-radius: 8px; padding: 8px 10px; }
.ig-sm-empty { margin: 4px 0 0; font-size: 12.5px; color: var(--ig-muted);
  line-height: 1.5; background: #FAFAFB; border: 1px solid var(--ig-line);
  border-radius: 8px; padding: 10px 12px; }

/* "never" is the answer, and it is not an error state. It is not red. */
.ig-sm-never { font-variant-numeric: tabular-nums; color: var(--ig-ink); }

.ig-sm-lanes { margin: 10px 0 2px; }
.ig-sm-lane { margin: 0 0 4px; font-size: 12.5px; color: var(--ig-depth); font-weight: 500; }
.ig-sm-lane.is-soon { color: var(--ig-muted); font-weight: 400; }

/* The client's frame, where the rejection list used to be: their API, their choice. */
.ig-sm-more { margin: 8px 0 2px; font-size: 12.5px; color: var(--ig-muted); line-height: 1.5; }
/* The pre-fill sentence. Andrew: "we already know this about you; correct us if we're
   wrong." This is the sentence that turns a filled box from a magic trick into
   evidence, so it reads as provenance and not as a hint. */
.ig-f-why { margin: 4px 0 0; font-size: 11.5px; line-height: 1.45;
  color: var(--ig-green-fg); background: var(--ig-green-bg);
  border-radius: 6px; padding: 6px 8px; }
/* ---- W82: the Telstra Health data-scope panel -------------------------------------
   Brand tokens only, never hexes.

   THIS BLOCK EXISTS BECAUSE OF A BUG THE ROUTE COULD NOT SHOW ME. I rendered the 13
   refusal families as `.ig-row` dt/dd first. `.ig-row` is `display:flex` with
   `flex:none` on the dt — it is built for a SHORT label against a SHORT value
   ("Coverage" / "72 of 72 homes"). Given a 60-character family name and a
   900-character reason, the dt took the row and the dd wrapped to roughly one word
   per line, overflowing the panel sideways behind a horizontal scrollbar.

   The API was 200. The partition was 4 + 698 = 702. Every assertion passed. The whole
   argument of the page was present, correct, and unreadable. That is FAILURE_MODES #23
   — the number stopped lying and the screen never said it — and the only reason it did
   not ship is that I opened the page and looked at it. */
.ig-scope { margin-top: 4px; }

.ig-h3 { font-size: 13px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
         color: var(--ig-muted); margin: 24px 0 10px; }

/* A refusal is prose, so it gets a block, not a table cell. */
.ig-scope-fam { border: 0.67px solid var(--ig-line); border-radius: 10px;
                padding: 12px 14px; margin: 0 0 8px; }

.ig-scope-fam-h { font-size: 12px; color: var(--ig-muted); margin: 0 0 6px; }
.ig-scope-fam-h b { font-weight: 600; }

.ig-scope-why { font-size: 13px; line-height: 1.55; margin: 0; overflow-wrap: anywhere; }

/* The taken endpoints ARE short-label/short-value pairs, so they keep .ig-row — but a
   path is long enough to squeeze the dataset, so this one row type is allowed to wrap
   rather than inheriting the flex:none that caused the bug above. */
.ig-scope .ig-row { align-items: flex-start; }
.ig-scope .ig-row dt { flex: 0 1 auto; overflow-wrap: anywhere; }
.ig-scope .ig-row dd { overflow-wrap: anywhere; }
