/* fingerprint.css — LOCKED 4 Sep 2026 (CEO). SYSTEM-WIDE.
 *
 * PALETTE CHANGED 4 Sep 2026 (CEO): the panel was dark on portals that are all
 * light, so it read as a foreign object. It now uses the modal convention every
 * portal already shares — a WHITE card on a navy scrim — and the values below
 * are the clinic portal's own tokens, not new ones invented here. Layout,
 * gesture and structure are untouched; only colour moved.
 *
 * The glyph and the panel look the same in every portal. A portal that wants a
 * different fingerprint is how one control starts meaning two things — the
 * lesson the SOP gesture already cost us. Portals may set --nnsfp-* tokens to
 * match their own ground; nothing else.
 *
 * Every selector is namespaced .nnsfp-* because this file lands in portals whose
 * own CSS uses generic class names, and the clinic fork already proved that a
 * shared panel can be silently restyled by a host's stylesheet.
 */

:root {
  /* Taken from the clinic portal's own palette. All three consumers already
     agree on this: .modal is white, the scrim is navy at 55%. */
  --nnsfp-panel:    #FFFFFF;              /* the card itself — .modal */
  --nnsfp-panel2:   #F5F6F8;              /* inset controls: search, segments, buttons */
  --nnsfp-head:     #FAFBFC;              /* header + footer strips — the portal's --paper */
  --nnsfp-line:     #E2E5EC;
  --nnsfp-line2:    #CBD2DC;              /* same line one step up, for hover borders */
  --nnsfp-linesoft: #EEF0F4;              /* rules between table rows */
  --nnsfp-hover:    #F5F6F8;              /* row hover */

  /* The portal's three text levels. --dim is its --ink-3, which the portal
     itself uses for .modal-subtitle at 10.5px, so it is proven legible at the
     sizes this panel sets. Its faintest ink (#B0B7C4) is a hairline colour and
     is deliberately NOT used for text here. */
  --nnsfp-tx:       #14253F;
  --nnsfp-mut:      #4A566E;
  --nnsfp-dim:      #7A8497;

  --nnsfp-acc:      #2E5C9E;
  --nnsfp-accsoft:  #E6EEF8;
  --nnsfp-accline:  #B9CCE4;
  --nnsfp-good:     #2D9A5B;
  --nnsfp-warn:     #C9851E;
  --nnsfp-warnsoft: #FBF1DD;
  --nnsfp-warnhov:  #F7E7C7;
  --nnsfp-warnline: #E8D4A8;
  --nnsfp-bad:      #B83A2E;

  --nnsfp-scrim:    rgba(20,37,63,.55);   /* the portal's own modal backdrop */
  --nnsfp-shadow:   0 30px 80px rgba(0,0,0,.30);
}

/* ---------------------------------------------------------------- glyph --- */
/* POINTER-EVENTS STAYS `auto`. The glyph is hidden by opacity alone.
 *
 * The first cut made it `pointer-events:none` until the host matched :hover,
 * which deadlocks: the hit test falls THROUGH the glyph to the host, so the
 * glyph can never itself become the hovered element that would enable it. A
 * person escapes that by crossing the row on the way in; a cursor that arrives
 * without crossing (window focus, tab switch, an assistive pointer) does not,
 * and neither does any harness — the control was untestable for the same reason
 * it was fragile.
 *
 * The theoretical cost is an invisible click target. It is theoretical: opacity
 * reaches full in 160ms on pointerenter, so the glyph is visible well before a
 * click lands, and it sits inside a row that is itself clickable. */
.nnsfp-g {
  position: relative; display: inline-flex; align-items: center; gap: 5px;
  border: 0; background: none; padding: 4px; margin: -4px; border-radius: 7px;
  color: var(--nnsfp-mut); cursor: pointer; line-height: 0;
  opacity: 0;
  transition: opacity .16s ease, color .12s ease, background .12s ease;
}
.nnsfp-g svg { width: 17px; height: 17px; display: block; }
.nnsfp-g .nnsfp-c {
  font: 600 10.5px/1 -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
  color: var(--nnsfp-dim); position: relative; top: .5px;
}

/* HOVER REVEAL is the locked default (CEO, 3 Sep 2026): zero ink until the
 * cursor is already on the row. No modifier — Option is Touchpoint estate-wide
 * and Shift was retired on 1 Sep, and a *reveal* gesture is global rather than
 * scoped to what is under the cursor, so it would collide with both. */
/* DESCENDANT, not child. The glyph lives inside the small span that carries the
 * data attributes, but the thing a person hovers is the ROW the host marked. A
 * child combinator only ever matched that inner span, so "hover the row to
 * reveal" -- the whole locked behaviour -- silently did not work: you had to
 * find an invisible 30px target first. */
.nnsfp-host:hover .nnsfp-g,
.nnsfp-host:focus-within .nnsfp-g,
.nnsfp-host.nnsfp-armed .nnsfp-g,
.nnsfp-g:hover { opacity: .85; }

/* The host carries the glyph's box. Left `inline`, the button's negative margin
 * overflows its own parent, so the parent's rect and the button's rect disagree
 * by 8px in both axes and every hit test near the edge resolves to the wrong
 * element. */
.nnsfp-host { display: inline-flex; align-items: center; gap: 6px; }
/* ...but a host that is also a layout row keeps its own display. */
.nnsfp-host.nnsfp-keepdisplay { display: revert; }

/* ARMED IS SET IN JS on pointerenter, and :hover is kept only as the no-JS
 * fallback. Relying on :hover alone made the glyph inert at the instant it was
 * pointed at: the button is pointer-events:none until its parent matches
 * :hover, so a hit test that resolves before that style applies lands on the
 * PARENT and the click is swallowed. The same portal already learned this once
 * with the SOP morph, which was sampled on mousemove and nowhere else. */
.nnsfp-g:hover { color: var(--nnsfp-acc); background: var(--nnsfp-accsoft); }
.nnsfp-g:hover .nnsfp-c { color: var(--nnsfp-acc); }

/* Keyboard reachability is NOT conditional on hover in any mode — a control you
 * can only reach with a mouse is not a control. */
.nnsfp-g:focus-visible {
  opacity: 1 !important;
  outline: 2px solid var(--nnsfp-acc); outline-offset: 1px;
}

.nnsfp-g[data-mode="always"] { opacity: .26; }
.nnsfp-host:hover .nnsfp-g[data-mode="always"] { opacity: .85; }

/* unopened marker */
.nnsfp-g .nnsfp-dot {
  position: absolute; top: 1px; right: 1px; width: 6px; height: 6px;
  border-radius: 50%; background: var(--nnsfp-warn);
  border: 1.5px solid var(--nnsfp-panel);
}
.nnsfp-g.nnsfp-hasflag svg { color: var(--nnsfp-warn); }

/* ---- PHI-BLOCKED: present, struck through, inert -------------------------
 * It must be legible as "there is a trail here and it is not for you" WITHOUT
 * a click, because clicking is exactly what it refuses to reward. */
.nnsfp-g.nnsfp-blocked {
  opacity: .30; cursor: not-allowed; color: var(--nnsfp-dim);
}
/* Visible, never actionable. Its click handler also stops the event, so this is
 * belt and braces rather than the only guard. */
.nnsfp-g.nnsfp-blocked:active { pointer-events: none; }
.nnsfp-host:hover .nnsfp-g.nnsfp-blocked { opacity: .48; }
.nnsfp-g.nnsfp-blocked:hover { color: var(--nnsfp-dim); background: none; }
.nnsfp-g.nnsfp-blocked::after {
  content: ""; position: absolute; left: 1px; right: 1px; top: 50%;
  height: 1.5px; background: currentColor; transform: rotate(-24deg);
  transform-origin: center; opacity: .9; pointer-events: none;
}
.nnsfp-g.nnsfp-blocked .nnsfp-c { display: none; }

/* ---------------------------------------------------------------- panel --- */
.nnsfp-scrim {
  position: fixed; inset: 0; background: var(--nnsfp-scrim);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  z-index: 2147483000; display: none;
  align-items: flex-start; justify-content: center; padding: 60px 20px 40px;
}
.nnsfp-scrim.nnsfp-open { display: flex; }
.nnsfp-card {
  width: min(880px, 100%); background: var(--nnsfp-panel);
  border: 1px solid var(--nnsfp-line); border-radius: 14px;
  box-shadow: var(--nnsfp-shadow); overflow: hidden;
  animation: nnsfp-pop .13s ease-out;
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif;
  color: var(--nnsfp-tx); text-align: left;
}
@keyframes nnsfp-pop { from { opacity: 0; transform: translateY(-6px) scale(.99); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .nnsfp-card { animation: none; } }

.nnsfp-head { padding: 15px 18px 13px; border-bottom: 1px solid var(--nnsfp-line); display: flex; gap: 14px; align-items: flex-start; }
.nnsfp-head .nnsfp-t { flex: 1; min-width: 0; }
.nnsfp-head h3 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: var(--nnsfp-tx); }
.nnsfp-head .nnsfp-m { color: var(--nnsfp-mut); font-size: 12px; margin-top: 3px; }
.nnsfp-ib {
  border: 1px solid var(--nnsfp-line); background: var(--nnsfp-panel2); color: var(--nnsfp-mut);
  border-radius: 7px; width: 28px; height: 28px; font-size: 14px; cursor: pointer;
  flex: none; display: grid; place-items: center; padding: 0;
}
.nnsfp-ib:hover { color: var(--nnsfp-tx); border-color: var(--nnsfp-line2); }
.nnsfp-ib:focus-visible { outline: 2px solid var(--nnsfp-acc); outline-offset: 1px; }

.nnsfp-integ { display: flex; gap: 9px; align-items: flex-start; padding: 9px 18px; font-size: 12px;
  border-bottom: 1px solid var(--nnsfp-line); background: var(--nnsfp-head); color: var(--nnsfp-mut); }
.nnsfp-integ .nnsfp-ok { color: var(--nnsfp-good); }
.nnsfp-integ .nnsfp-wn { color: var(--nnsfp-warn); }
.nnsfp-integ code { font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--nnsfp-dim); }

.nnsfp-tools { display: flex; gap: 10px; align-items: center; padding: 11px 18px;
  border-bottom: 1px solid var(--nnsfp-line); flex-wrap: wrap; }
.nnsfp-seg { display: flex; background: var(--nnsfp-panel2); border: 1px solid var(--nnsfp-line); border-radius: 8px; padding: 2px; }
.nnsfp-seg button { border: 0; background: none; color: var(--nnsfp-mut); font: inherit; font-size: 12.5px;
  padding: 5px 12px; border-radius: 6px; cursor: pointer; white-space: nowrap; }
.nnsfp-seg button.nnsfp-on { background: var(--nnsfp-panel); color: var(--nnsfp-tx);
  box-shadow: 0 1px 2px rgba(20,37,63,.14); }
.nnsfp-seg button:focus-visible { outline: 2px solid var(--nnsfp-acc); outline-offset: -1px; }
.nnsfp-search { flex: 1; min-width: 170px; background: var(--nnsfp-panel2);
  border: 1px solid var(--nnsfp-line); border-radius: 8px; color: var(--nnsfp-tx);
  font: inherit; font-size: 13px; padding: 7px 11px; }
.nnsfp-search:focus { outline: 2px solid var(--nnsfp-acc); outline-offset: -1px; border-color: transparent; }
.nnsfp-search::placeholder { color: var(--nnsfp-dim); }

.nnsfp-tblwrap { max-height: min(52vh, 430px); overflow: auto; }
.nnsfp-card table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.nnsfp-card thead th { position: sticky; top: 0; background: var(--nnsfp-head); z-index: 2; text-align: left;
  font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--nnsfp-dim);
  font-weight: 600; padding: 9px 12px; border-bottom: 1px solid var(--nnsfp-line);
  cursor: pointer; user-select: none; white-space: nowrap; }
.nnsfp-card thead th:hover { color: var(--nnsfp-mut); }
.nnsfp-card thead th .nnsfp-ar { opacity: .35; font-size: 9px; padding-left: 3px; }
.nnsfp-card thead th.nnsfp-sorted { color: var(--nnsfp-acc); }
.nnsfp-card thead th.nnsfp-sorted .nnsfp-ar { opacity: 1; }
.nnsfp-card tbody td { padding: 9px 12px; border-bottom: 1px solid var(--nnsfp-linesoft); vertical-align: top; color: var(--nnsfp-tx); }
.nnsfp-card tbody tr:hover { background: var(--nnsfp-hover); }
.nnsfp-card tbody tr.nnsfp-flag { background: var(--nnsfp-warnsoft); }
.nnsfp-card tbody tr.nnsfp-flag:hover { background: var(--nnsfp-warnhov); }
.nnsfp-who { font-weight: 500; }
.nnsfp-id { font: 11.5px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--nnsfp-mut); }
.nnsfp-when { white-space: nowrap; }
.nnsfp-when span { display: block; color: var(--nnsfp-dim); font-size: 11px; }
.nnsfp-act { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.nnsfp-act i { width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--nnsfp-dim); font-style: normal; }
.nnsfp-act[data-a="viewed"] i { background: #2E5C9E; }
.nnsfp-act[data-a="printed"] i { background: #6B4FA8; }
.nnsfp-act[data-a="emailed"] i, .nnsfp-act[data-a="faxed"] i { background: #0F7FA5; }
.nnsfp-act[data-a="modified"] i { background: var(--nnsfp-warn); }
.nnsfp-act[data-a="downloaded"] i { background: var(--nnsfp-bad); }
.nnsfp-act[data-a="signed"] i { background: var(--nnsfp-good); }
.nnsfp-actcell { white-space: nowrap; }
.nnsfp-to { color: var(--nnsfp-mut); }
.nnsfp-to em { color: var(--nnsfp-dim); font-style: italic; }
.nnsfp-v { font: 600 10px/1 ui-monospace, Menlo, monospace; color: var(--nnsfp-dim);
  border: 1px solid var(--nnsfp-line); border-radius: 4px; padding: 2px 4px; margin-left: 6px; }
.nnsfp-v.nnsfp-stale { color: var(--nnsfp-warn); border-color: var(--nnsfp-warnline); }
.nnsfp-fl { color: var(--nnsfp-warn); cursor: help; }
.nnsfp-empty { padding: 34px 18px; text-align: center; color: var(--nnsfp-dim); font-size: 13px; }
.nnsfp-empty b { display: block; color: var(--nnsfp-mut); font-size: 14px; margin-bottom: 5px; }

.nnsfp-foot { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 11px 18px;
  border-top: 1px solid var(--nnsfp-line); background: var(--nnsfp-head); font-size: 12px; color: var(--nnsfp-dim); }
.nnsfp-foot .nnsfp-grow { flex: 1; }
.nnsfp-btn { border: 1px solid var(--nnsfp-line); background: var(--nnsfp-panel2); color: var(--nnsfp-mut);
  border-radius: 7px; padding: 6px 11px; font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; }
.nnsfp-btn:hover { color: var(--nnsfp-tx); border-color: var(--nnsfp-line2); }
.nnsfp-btn:focus-visible { outline: 2px solid var(--nnsfp-acc); outline-offset: 1px; }
.nnsfp-btn.nnsfp-on { color: var(--nnsfp-acc); border-color: var(--nnsfp-accline); background: var(--nnsfp-accsoft); }
.nnsfp-rec { font-size: 11px; color: var(--nnsfp-dim); display: flex; align-items: center; gap: 5px; }

.nnsfp-help { display: none; padding: 16px 18px; border-top: 1px solid var(--nnsfp-line);
  background: var(--nnsfp-head); font-size: 12.5px; color: var(--nnsfp-mut); }
.nnsfp-help.nnsfp-open { display: block; }
.nnsfp-help dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; }
.nnsfp-help dt { color: var(--nnsfp-tx); font-weight: 600; white-space: nowrap; }
.nnsfp-help dd { margin: 0; }

.nnsfp-note { padding: 14px 18px; color: var(--nnsfp-mut); font-size: 12.5px; line-height: 1.6; }

/* ---------------------------------------------------- certificate dialog --- */
.nnsfp-cert { display: none; padding: 16px 18px; border-top: 1px solid var(--nnsfp-line);
  background: var(--nnsfp-head); font-size: 12.5px; color: var(--nnsfp-mut); }
.nnsfp-cert.nnsfp-open { display: block; }
.nnsfp-certhead { font-size: 12px; font-weight: 600; color: var(--nnsfp-tx);
  letter-spacing: .04em; text-transform: uppercase; margin-bottom: 7px; }
.nnsfp-certnote { margin: 0 0 12px; line-height: 1.6; max-width: 70ch; }
.nnsfp-cert label { display: block; margin-bottom: 10px; color: var(--nnsfp-dim);
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase; }
.nnsfp-cert select, .nnsfp-cert input[type="text"] {
  display: block; width: 100%; margin-top: 5px; background: var(--nnsfp-panel2);
  border: 1px solid var(--nnsfp-line); border-radius: 7px; color: var(--nnsfp-tx);
  font: inherit; font-size: 13px; padding: 7px 10px; text-transform: none; letter-spacing: 0; }
.nnsfp-cert select:focus, .nnsfp-cert input:focus {
  outline: 2px solid var(--nnsfp-acc); outline-offset: -1px; border-color: transparent; }
.nnsfp-certfile { display: flex !important; align-items: center; gap: 8px;
  text-transform: none !important; letter-spacing: 0 !important;
  font-size: 12.5px !important; color: var(--nnsfp-mut) !important; }
.nnsfp-certfile input { width: auto !important; margin: 0 !important; accent-color: var(--nnsfp-acc); }
.nnsfp-certacts { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.nnsfp-certmsg { color: var(--nnsfp-warn); font-size: 12px; }
