/* ============================================================================
   InfraEdge — product and investor infographics.

   Partner to partials/diagrams-product.js. Everything is prefixed dp- so it
   cannot collide with concepts.css or style.css. Tokens only, no raw hex, no
   shadows.

   Most of the drawings are .schematic .draw and inherit their line vocabulary
   and their self-draw from concepts.css and base.css. What lives here is the
   handful of shapes those primitives do not cover: the score gauge, the
   sparkline cells, the risk strip and the materiality scatter.
   ========================================================================= */

/* ==========================================================================
   Shared — the specimen label.

   Every invented output on this site says so, at the top, in the same voice.
   The alternative is a chart a reader assumes is a real customer's data, and
   the brand rule against inventing statistics is not satisfied by a quiet
   caption at the bottom.
   ========================================================================== */
.dp-specimen-block {
  display: grid; gap: .35rem; margin-bottom: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border: 1px dashed var(--line-strong); border-radius: var(--r-s);
  background: var(--gold-tint);
}
.dp-specimen {
  margin: 0; display: flex; align-items: center; gap: .5rem;
  font-size: var(--t-micro); letter-spacing: .1em; text-transform: uppercase;
  font-weight: 600; color: var(--ink);
}
.dp-specimen-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--gold-400); border: 1px solid var(--navy-900); flex: none; }
.dp-specimen-block .small { margin: 0; }

/* ==========================================================================
   readinessOutput — the specimen score card.
   ========================================================================== */
.dp-score-grid { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: clamp(1.25rem, 3vw, 2.5rem); align-items: start; }
.dp-score-heading { margin: 0 0 .6rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 600; }
.dp-score-heading + * { margin-bottom: var(--s-3); }

.dp-gauge-wrap { position: relative; width: 140px; margin: 0 auto; }
.dp-gauge { display: block; width: 140px; height: 140px; }
.dp-gauge-track { fill: none; stroke: var(--line); stroke-width: 10; }
.dp-gauge-arc { fill: none; stroke: var(--sky-600); stroke-width: 10; stroke-linecap: round; }
.dp-gauge-label {
  position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: .1rem;
}
.dp-gauge-label b { font-size: var(--t-h2); font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
.dp-gauge-label span { font-size: var(--t-micro); color: var(--ink-quiet); }
.dp-band { margin: var(--s-2) 0 0; text-align: center; font-size: var(--t-micro); color: var(--ink-soft); }
.dp-band span:last-child { display: block; margin-top: .4rem; }

.dp-pillars { display: grid; gap: .5rem; }
.dp-pillar-row { display: grid; grid-template-columns: 110px minmax(0, 1fr) 34px; gap: .75rem; align-items: center; font-size: var(--t-small); }
.dp-pillar-track { height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
.dp-pillar-fill { display: block; height: 100%; background: var(--sky-600); border-radius: 3px; }
.dp-pillar-row .num { text-align: right; color: var(--ink-soft); font-size: var(--t-small); }

.dp-risks { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-3); }
.dp-risks > div {
  display: grid; gap: .5rem; justify-items: start;
  padding: var(--s-2); border: 1px solid var(--line); border-radius: var(--r-s); background: var(--white);
  transition: border-color var(--dur-fast) ease;
}
.dp-risks > div:hover { border-color: var(--hover-border); }
.dp-risks .stat b { font-size: var(--t-h3); }

@media (max-width: 760px) {
  .dp-score-grid { grid-template-columns: 1fr; }
  .dp-gauge-wrap { margin: 0; }
  .dp-band { text-align: left; }
  .dp-risks { grid-template-columns: 1fr; }
  .dp-pillar-row { grid-template-columns: 96px minmax(0, 1fr) 30px; }
}

/* ==========================================================================
   assuranceTable — sparkline cells and the risk strip.

   Trend colour is deliberately uniform. Severity is carried by the badge
   text next to it, so a reader who cannot distinguish the colours loses
   nothing — and a row of red and green lines would be a traffic-light
   system, which is off-brand and fails on colour-only meaning.
   ========================================================================== */
.dp-spark-cell { display: inline-flex; align-items: center; gap: .6rem; }
.dp-spark { width: 92px; height: 22px; flex: none; }
.dp-spark polyline { fill: none; stroke: var(--sky-600); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.dp-trend-note { font-family: var(--font); font-size: var(--t-micro); letter-spacing: .06em; color: var(--ink-quiet); text-transform: uppercase; }

.dp-risktime { margin-top: var(--s-4); }
.dp-risktime svg { width: 100%; height: auto; }
.dp-risktime .line { fill: none; stroke: var(--navy-900); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.dp-risktime .threshold { stroke: var(--slate-500); stroke-width: 1; stroke-dasharray: 5 4; }
.dp-risktime .flag { fill: var(--gold-400); stroke: var(--navy-900); stroke-width: 1.2; }
.dp-risktime p { margin: .6rem 0 0; }

@media (max-width: 620px) {
  .dp-spark { width: 60px; }
  .dp-trend-note { display: none; }
}

/* ==========================================================================
   driftDetection — the "does not equal" and its outcome.

   U+2260 is outside both self-hosted font subsets, so the glyph is drawn as
   three strokes rather than set as text. Do not replace it with the
   character: it would silently fall back to the system font mid-diagram.
   ========================================================================== */
.dp-drift { display: grid; gap: var(--s-3); }
.dp-neq { stroke: var(--amber-ink); stroke-width: 4; stroke-linecap: round; fill: none; }
.dp-drift-outcome {
  display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line); border-radius: var(--r-s); background: var(--mist);
}
.dp-drift-outcome p { margin: 0; }

/* ==========================================================================
   investorSeverityMatrix — the materiality scatter.

   Restrained on purpose: one quadrant tinted, one dividing pair of hairlines,
   numbered dots. The authority is the table underneath, which names each
   finding's complexity and materiality in words — the plot is a way to scan
   the shape, not the record.
   ========================================================================== */
/* A scatter of seven points does not want to be full-bleed. Left unbounded it
   stretches to the container and scales every label and dot with it, which
   reads as a dashboard rather than as the restrained analytical aside the
   page needs. */
.dp-imat { max-width: 560px; margin: 0 auto; display: block; }

.dp-imat-quadrant { fill: var(--sky-tint); }
.dp-imat-label { font-family: var(--font); font-size: 12px; letter-spacing: .12em; fill: var(--sky-700); font-weight: 600; }
.dp-imat-div { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 5 4; fill: none; }
.dp-imat-point circle { fill: var(--white); stroke: var(--navy-900); stroke-width: 1.8; }
.dp-imat-point text { font-family: var(--font); font-size: 10px; font-weight: 700; fill: var(--navy-900); }
.dp-imat-legend { margin-top: var(--s-3); }

/* The scatter is square-ish and stops being readable much below 420px, where
   the numbered dots start to overlap. The table below carries everything. */
@media (max-width: 560px) {
  .dp-imat-label { display: none; }
}

/* ==========================================================================
   edgeSignalFlow — the two onward paths, as links.

   They used to be <a> elements drawn inside the SVG, which carries
   role="img": one picture, containing four controls. That is the
   nested-interactive finding from the September 2026 audit, and it shipped in
   the same shape on the lifecycle ring. The drawing is now a drawing and the
   destinations are named underneath, where a keyboard reaches them without a
   focus ring drawn around a rectangle in a 960-unit viewBox, and where they
   are still legible on a phone.
   ========================================================================== */
.signal-flow { display: grid; gap: var(--s-2); }
.signal-onward {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem;
  max-width: 640px;
}
.signal-onward a {
  display: block; padding: .7rem .85rem;
  border: 1px solid var(--line); border-radius: var(--r-s);
  background: var(--white); text-decoration: none; color: var(--ink);
  font-size: var(--t-small); line-height: 1.35;
  transition: border-color var(--dur-fast) ease;
}
.signal-onward a:hover { border-color: var(--hover-border); }
.signal-onward a:hover b { color: var(--hover-ink); }
.signal-onward b {
  display: block; font-weight: 700; letter-spacing: -0.01em; margin-bottom: .1rem;
}
.signal-onward span { display: block; color: var(--ink-soft); }

@media (max-width: 560px) {
  .signal-onward { grid-template-columns: 1fr; }
}

/* ==========================================================================
   keyExchangeHops — EdgePQ Check, where key exchange happens.

   The drawing is built from the shared schematic vocabulary (.s-box, .s-line,
   .s-gate for the gold key-exchange diamonds, .s-gold for the timeline), so
   all this needs is the stack around it. The drawing sits in its own wrapper
   so that below 900px only the picture pans, not the citation under it.

   Reduced motion: base.css already sets every [data-draw] stroke and every
   [data-draw-label] group to its final state; the rule below states it for
   this figure too, so the gold markers never wait on a transition.
   ========================================================================== */
.dp-kx { display: grid; gap: var(--s-2); }
.dp-kx-source { margin: 0; max-width: 68ch; }

@media (prefers-reduced-motion: reduce) {
  .dp-kx .draw [data-draw] { stroke-dashoffset: 0; transition: none; }
  .dp-kx .draw [data-draw-label] { opacity: 1; transition: none; }
}

/* ==========================================================================
   tfimpactVerdict and tfimpactPipeline — /tools/tfimpact.

   Plan text, resource addresses and commands are things a reader would type,
   so they are set in the mono face; every label stays in --font. The ticks
   are the forty-one changes as the plan line presents them: identical on
   purpose, in a quiet stroke so they read as texture rather than data.
   Reduced motion needs nothing here: base.css already renders .draw at its
   final state.
   ========================================================================== */
.schematic .tfi-plan { font-family: var(--mono); font-size: 15px; font-weight: 600; fill: var(--navy-900); }
.schematic .tfi-mono { font-family: var(--mono); font-size: 12.5px; fill: var(--ink-soft); }
.schematic .tfi-cmd { font-family: var(--mono); font-size: 13px; }
.schematic .tfi-ticks { fill: none; stroke: var(--slate-500); stroke-width: 2; stroke-linecap: round; }
.tfi-figure { display: grid; gap: var(--s-3); }
/* Commands and rule IDs set inline in the page's prose. Scoped to the tools
   pages, and this sheet only ships on a page with a drawing in it. */
body[data-page='tools'] main code { font-family: var(--mono); font-size: .92em; font-variant-ligatures: none; }
/* A grid column holding a pre must be allowed to shrink, or the code widens
   the page on a phone instead of scrolling inside its own box. */
.tfi-col { min-width: 0; }
/* A rule ID is one token; broken across lines it stops being searchable. */
.tfi-id { white-space: nowrap; }
.tfi-col > h3 { margin-bottom: var(--s-2); }
.tfi-steps { margin: 0; padding-left: 1.25rem; list-style: decimal; display: grid; gap: .35rem; font-size: var(--t-small); color: var(--ink-soft); }
/* On a phone the five-column table squeezes "What happens" to a word per line.
   Hold a floor and let .table-wrap pan, the same bargain the drawings make. */
@media (max-width: 760px) {
  .tfi-figure table.data { min-width: 860px; }
  .tfi-figure table.data td:nth-child(3) { min-width: 17rem; }
  .tfi-rules table.data { min-width: 560px; }
}
