/* ──────────────────────────────────────────────────────────────────────────
   DeedFlex design tokens + shared components.  SANDBOX.
   Spec: ~/.claude/skills/saas-data-ux/references/visual-system.md

   One base unit (4px), four type sizes, one accent. Grey is load-bearing:
   "we don't know" must read as neither reassuring nor alarming, which is the
   entire point of the verdict model.
   ────────────────────────────────────────────────────────────────────────── */
:root{
  /* spacing — multiples of 4 only */
  --dx-1:4px;  --dx-2:8px;  --dx-3:12px; --dx-4:16px;
  --dx-6:24px; --dx-8:32px; --dx-10:40px; --dx-12:48px;

  /* type — four sizes, two weights */
  --dx-title:30px; --dx-section:19px; --dx-body:15px; --dx-meta:13px;

  /* status — each pairs with an icon and a word, never colour alone */
  --dx-ok:#4ade80;   --dx-ok-bg:rgba(74,222,128,.12);   --dx-ok-br:rgba(74,222,128,.28);
  --dx-warn:#fbbf24; --dx-warn-bg:rgba(251,191,36,.12); --dx-warn-br:rgba(251,191,36,.28);
  --dx-bad:#f87171;  --dx-bad-bg:rgba(248,113,113,.12); --dx-bad-br:rgba(248,113,113,.28);
  --dx-unk:#94a3b8;  --dx-unk-bg:rgba(148,163,184,.10); --dx-unk-br:rgba(148,163,184,.24);

  --dx-radius:10px; --dx-radius-pill:999px;
}

/* ── verdict + evidence ─────────────────────────────────────────────────── */
.dx-verdict{display:flex;align-items:center;justify-content:space-between;
  gap:var(--dx-3);flex-wrap:wrap;margin:0 0 var(--dx-2);
  padding-bottom:var(--dx-2);border-bottom:1px solid rgba(148,163,184,.18);}
.dx-word{font-size:var(--dx-body);font-weight:700;letter-spacing:.01em;
  display:inline-flex;align-items:center;gap:var(--dx-2);}
.dx-positive .dx-word{color:var(--dx-ok);}
.dx-caution  .dx-word{color:var(--dx-warn);}
.dx-negative .dx-word{color:var(--dx-bad);}
.dx-unknown  .dx-word{color:var(--dx-unk);}

.dx-ev{display:flex;align-items:center;gap:var(--dx-2);
  font-size:var(--dx-meta);color:var(--dx-unk);white-space:nowrap;}
.dx-bar{display:inline-block;width:56px;height:5px;border-radius:3px;
  background:rgba(148,163,184,.22);overflow:hidden;}
.dx-bar i{display:block;height:100%;background:var(--dx-unk);}
.dx-positive .dx-bar i{background:var(--dx-ok);}
.dx-caution  .dx-bar i{background:var(--dx-warn);}
.dx-negative .dx-bar i{background:var(--dx-bad);}
.dx-why{font-size:var(--dx-meta);color:var(--dx-unk);margin:0 0 var(--dx-2);}

/* ── card ───────────────────────────────────────────────────────────────── */
.dx-card{display:flex;flex-direction:column;gap:var(--dx-2);
  padding:var(--dx-4);border-radius:var(--dx-radius);}
.dx-addr{font-size:var(--dx-body);font-weight:600;line-height:1.35;}
.dx-sub{font-size:var(--dx-meta);color:var(--dx-unk);}
.dx-figs{display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--dx-3);margin-top:var(--dx-1);}
.dx-fig{display:flex;flex-direction:column;gap:2px;}
.dx-fig .k{font-size:var(--dx-meta);color:var(--dx-unk);}
.dx-fig .v{font-size:var(--dx-body);font-weight:700;
  font-variant-numeric:tabular-nums;}
.dx-foot{display:flex;align-items:center;justify-content:space-between;
  gap:var(--dx-3);margin-top:var(--dx-1);}

/* ── chips ──────────────────────────────────────────────────────────────── */
.dx-chip{display:inline-flex;align-items:center;gap:6px;
  padding:3px 10px;border-radius:var(--dx-radius-pill);
  font-size:var(--dx-meta);font-weight:600;border:1px solid transparent;}
.dx-chip--ok  {color:var(--dx-ok);  background:var(--dx-ok-bg);  border-color:var(--dx-ok-br);}
.dx-chip--warn{color:var(--dx-warn);background:var(--dx-warn-bg);border-color:var(--dx-warn-br);}
.dx-chip--bad {color:var(--dx-bad); background:var(--dx-bad-bg); border-color:var(--dx-bad-br);}
.dx-chip--unk {color:var(--dx-unk); background:var(--dx-unk-bg); border-color:var(--dx-unk-br);}

/* ── disclosure ─────────────────────────────────────────────────────────── */
.dx-more{border-top:1px solid rgba(148,163,184,.18);margin-top:var(--dx-3);}
.dx-more>summary{cursor:pointer;list-style:none;padding:var(--dx-3) 0;
  font-size:var(--dx-body);font-weight:600;display:flex;
  align-items:center;justify-content:space-between;gap:var(--dx-2);}
.dx-more>summary::-webkit-details-marker{display:none}
.dx-more>summary::after{content:"\f078";font-family:"Font Awesome 6 Free";
  font-weight:900;font-size:11px;color:var(--dx-unk);transition:transform .15s ease-out;}
.dx-more[open]>summary::after{transform:rotate(180deg);}

/* ── accessibility + motion ─────────────────────────────────────────────── */
.dx-card a,.dx-chip,.dx-more>summary{min-height:44px;}
.dx-inline-link{min-height:auto;}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
@media (max-width:640px){
  .dx-figs{flex-direction:column;align-items:flex-start;gap:var(--dx-2);}
  .dx-verdict{gap:var(--dx-2);}
}

/* ── Equal cards ──────────────────────────────────────────────────────────
   A reader comparing a row of cards is comparing POSITIONS, not reading six
   layouts, so anything that shifts a row between cards costs a re-read.
   Measured on the coverage grid before this block: the cards were already the
   same height (527px) and the verdict, address and figures all aligned -- but
   the action row sat at 366 / 397 / 434 / 434. Up to 68px of drift, caused by
   the optional middle rows differing per card.

   Four rules, in the order they have to be applied. The height was already
   right, so only the last three do work here; rule 1 is written down because
   leaving it implicit is how it goes missing the next time.                */

/* 1. Cards share a height. CSS Grid already stretches items, so this is a
      statement of intent rather than a change -- but a future flex container
      would not, and this is where someone will look. */
.card-grid{align-items:stretch;}
.card-grid>.dx-card{height:100%;}
/*    ...and every ROW shares a height too. Grid sizes each row to its own
      tallest card, so a trailing card alone on the last row came out 30px
      shorter than the three above it -- measured 263 against 293. 1fr on the
      implicit rows makes the whole grid uniform, which is only safe because
      rule 2 pins the foot: the slack lands above the action row, where it
      reads as breathing space, not as a card that failed to fill. */
.card-grid{grid-auto-rows:1fr;}

/* 2. Pin the action row to the bottom. The slack then falls INSIDE the card,
      above the foot, instead of piling under short content. This is what
      fixes the 68px drift: every foot lands on the same line regardless of
      how many optional rows sit above it. */
.dx-card>.dx-foot{margin-top:auto;}

/* 3. Reserve one height for the foot. A one-line date and a wrapped two-line
      one do not round to the same box, and that difference travels upward.
      Equalising the children drifts by a few px; fix the container. */
.dx-card>.dx-foot{min-height:44px;}

/* 4. Clamp the one variable-length text block. An address that wraps to two
      lines on one card and one on another shifts everything below it, so
      reserve two lines and clamp to two -- reserve, not just clamp, or a
      one-line address still rides up. */
.dx-addr{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
  min-height:calc(2 * 1.35 * var(--dx-body));
}

/* The named-gap line has the same problem one level down: present on caution
   and unknown cards, absent on clean ones. Reserve its line so the identity
   block starts at the same y on every card in the row. */
.dx-card>.dx-why{min-height:1.4em;}
