/* Diagram visual system.

   Everything the architecture canvas paints with is declared here, once, as a
   custom property. Two rules keep it that way:

   1. No hex value appears anywhere else - not in JavaScript, not in another
      stylesheet - so dark mode is this file's problem alone.
   2. Colour that has to survive the SVG/PNG/PDF export is written onto the
      element as a presentation attribute by diagram.js, resolved from the
      token below. The export clones the live SVG into a standalone file where
      only exporter.js's inlined stylesheet applies, so a colour left to a
      class here would simply vanish on the way out. Fonts, cursors, hover and
      dimming stay as rules, because those the export either keeps or does not
      need.

   Category colour is the coarse signal - eight hues a reader can hold in their
   head. The service icon carries the specific identity. */

:root {
  /* Resource categories. Chosen for separation in hue, not just lightness, so
     they stay distinguishable to the most common colour vision deficiencies
     and when printed. */
  --cat-edge: #0b7285;
  --cat-network: #6741d9;
  --cat-loadbalancer: #9c36b5;
  --cat-compute: #d9730d;
  --cat-database: #1971c2;
  --cat-storage: #2b8a3e;
  --cat-security: #c2255c;
  --cat-other: #5c6b7a;

  /* Reachability. Public is deliberately the warmest: on a security review it
     is the thing to look at first. */
  --exposure-public: #b35309;
  --exposure-private: #2f7561;
  --exposure-managed: #4d6a89;
  --exposure-unknown: #78858f;

  --provider-other: #6b7c8f;

  /* Containment. Each nesting level gets its own weight, fill and line so a
     region, a VPC and a subnet are never mistaken for one another. */
  --box-account-line: #6f7d8b;
  --box-account-fill: #eef1f5;
  --box-region-line: #0b7285;
  --box-region-fill: #f4f9fa;
  --box-vpc-line: #6741d9;
  --box-vpc-fill: #f8f6fe;
  --box-subnet-public-line: #7a8f1f;
  --box-subnet-public-fill: #fbfdf3;
  --box-subnet-private-line: #3b6ea5;
  --box-subnet-private-fill: #f4f8fc;
  --box-plain-line: #8593a2;
  --box-plain-fill: #fbfcfd;

  /* Official icons are drawn for a light ground - the two sets between them
     fill shapes in #ffffff and #f2f2f2, which would vanish on a dark surface.
     Every icon therefore sits on its own plate, which stays light in both
     schemes so the artwork is shown as its owner intended rather than
     recoloured. In light mode the plate is the node's own surface and
     disappears, which is intended: it is not a contrast failure to fix. The
     hairline is what gives the icon column an edge where an icon does not
     paint to its own boundary. */
  --icon-plate: #ffffff;
  --icon-plate-line: #e7ecf1;

  /* Port and protocol on a relationship line. The label rides over whatever
     the line crosses, so it carries its own plate. */
  --edge-label-ink: #45566a;
  --edge-label-fill: #ffffff;
  --edge-label-line: #d5dde5;
}

:root[data-theme="dark"] {
    --cat-edge: #38b6c8;
    --cat-network: #9a86f5;
    --cat-loadbalancer: #d47ae8;
    --cat-compute: #f0a35e;
    --cat-database: #61a5f2;
    --cat-storage: #6bc98a;
    --cat-security: #f083a8;
    --cat-other: #93a3b3;

    --exposure-public: #e59b45;
    --exposure-private: #5cbfa2;
    --exposure-managed: #8fb0d0;
    --exposure-unknown: #7d8b99;

    --provider-other: #8497a8;

    --box-account-line: #5f6e7c;
    --box-account-fill: #141a21;
    --box-region-line: #2f8b98;
    --box-region-fill: #121c20;
    --box-vpc-line: #6f5cc4;
    --box-vpc-fill: #171725;
    --box-subnet-public-line: #6f7f34;
    --box-subnet-public-fill: #1a1d14;
    --box-subnet-private-line: #3f6a94;
    --box-subnet-private-fill: #141b23;
    --box-plain-line: #6d7c89;
    --box-plain-fill: #1b222b;

    /* The plate has to stay light, but a near-white one glares: forty of them
       against a #0f1419 canvas read as a field of lit tiles with a diagram
       between them. Down to roughly 80% of the light-mode plate, with a
       mid-tone rim that ties each tile to the dark ground instead of letting
       it halo - which is what the eye reads as glare. It cannot go darker
       than this without losing the icons' own white fills. */
    --icon-plate: #d5dce4;
    --icon-plate-line: #97a3b0;

    --edge-label-ink: #9fb3c6;
    --edge-label-fill: #131a22;
    --edge-label-line: #35434f;
}

/* ---------- containment boxes ---------- */

/* A box's fill, stroke, width and dash are presentation attributes set by
   diagram.js from the tokens above, so the export keeps them. Only type lives
   here - exporter.js styles .grp-label itself, so a label there falls back to
   the muted colour rather than losing its font. */
.grp-label.kind-account { fill: var(--box-account-line); font-weight: 700; letter-spacing: .12em; }
.grp-label.kind-region { fill: var(--box-region-line); }
.grp-label.kind-vpc { fill: var(--box-vpc-line); }
.grp-label.kind-subnet {
  fill: var(--box-subnet-private-line);
  text-transform: none; letter-spacing: .01em; font-size: 10px;
}
.grp-label.kind-subnet.public { fill: var(--box-subnet-public-line); }
.grp-label.kind-application { fill: var(--cat-other); }

/* The sub-label is deliberately quieter than the name at every level. */
.grp-sub { opacity: .8; }

.grp-icon { opacity: .95; }

/* ---------- relationship port labels ---------- */

/* A label's plate, text and position are presentation attributes written by
   diagram.js, so they survive the export. Only visibility lives here, because
   it is the one thing that depends on what the reader is doing.

   These four rules are ordered, not accidental. The last three are of equal
   specificity, so each overrides the one above it, and they read down as the
   rule for when a port is worth showing:

   1. never, on its own
   2. once the diagram is zoomed in far enough for 9px type, for every label
      that found room to sit without covering something
   3. except on a link outside the current selection, which is not part of the
      answer to the question just asked
   4. always, on the selected resource's links and on the line under the
      pointer, whatever the zoom and whether or not it found room. An
      explicitly asked-for label is never withheld. */
.edge-label { visibility: hidden; pointer-events: none; }
.diagram.labels-visible .edge-label:not(.crowded) { visibility: visible; }
.diagram .edge.dimmed + .edge-label { visibility: hidden; }
.diagram .edge.hot + .edge-label,
.diagram .edge-line:hover .edge-label { visibility: visible; }

/* A highlighted link's label joins the highlight rather than staying grey
   beside an accented line. */
.diagram .edge.hot + .edge-label .edge-label-text { fill: var(--accent); }
.diagram .edge.hot + .edge-label .edge-label-plate { stroke: var(--accent); }

/* ---------- legend ---------- */

.diagram-legend {
  /* Top right, because the canvas already has a legend bottom left: the two
     would collide on a narrow window. */
  position: absolute; right: 14px; top: 12px; z-index: 5;
  width: 296px; max-width: calc(100% - 28px);
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  box-shadow: var(--shadow); font-size: 11px; color: var(--muted);
  overflow: hidden;
}
.diagram-legend > summary {
  cursor: pointer; list-style: none; padding: 7px 11px;
  font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-2); display: flex; justify-content: space-between; gap: 10px;
}
.diagram-legend > summary::-webkit-details-marker { display: none; }
.diagram-legend > summary::after { content: "+"; color: var(--muted); font-weight: 600; }
.diagram-legend[open] > summary::after { content: "\2212"; }
.diagram-legend[open] > summary { border-bottom: 1px solid var(--line); }

.legend-body { padding: 9px 11px 10px; display: grid; gap: 10px; max-height: 48vh; overflow-y: auto; }
.legend-block { display: grid; gap: 4px; }
.legend-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3px 10px; }
.legend-rows { display: grid; gap: 3px; }
.legend-block h4 {
  margin: 0; font-size: 9px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.legend-row { display: flex; align-items: center; gap: 7px; color: var(--ink-2); }
.legend-note { font-size: 10px; line-height: 1.45; color: var(--muted); }

.legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.legend-swatch.cat-edge { background: var(--cat-edge); }
.legend-swatch.cat-network { background: var(--cat-network); }
.legend-swatch.cat-loadbalancer { background: var(--cat-loadbalancer); }
.legend-swatch.cat-compute { background: var(--cat-compute); }
.legend-swatch.cat-database { background: var(--cat-database); }
.legend-swatch.cat-storage { background: var(--cat-storage); }
.legend-swatch.cat-security { background: var(--cat-security); }
.legend-swatch.cat-other { background: var(--cat-other); }

.legend-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.legend-dot.exp-public { background: var(--exposure-public); }
.legend-dot.exp-private { background: var(--exposure-private); }
.legend-dot.exp-managed { background: var(--exposure-managed); }
.legend-dot.exp-unknown { background: var(--exposure-unknown); }

/* Miniature of the real box treatment, so the key looks like the diagram. */
.legend-box { width: 20px; height: 12px; border-radius: 3px; flex: none; }
.legend-box.kind-account { border: 1.6px solid var(--box-account-line); background: var(--box-account-fill); }
.legend-box.kind-region { border: 1.4px dashed var(--box-region-line); background: var(--box-region-fill); }
.legend-box.kind-vpc { border: 1.6px solid var(--box-vpc-line); background: var(--box-vpc-fill); }
.legend-box.kind-subnet-public { border: 1px solid var(--box-subnet-public-line); background: var(--box-subnet-public-fill); }
.legend-box.kind-subnet-private { border: 1px solid var(--box-subnet-private-line); background: var(--box-subnet-private-fill); }
