/* ============================================================
   BALOR3 — shared stylesheet
   Loaded by every page. Change a token below and it updates
   across the whole site.
   ============================================================ */

:root {
  --font-body: 'Satoshi', Inter, sans-serif;
  --font-display: 'Cabinet Grotesk', 'Satoshi', sans-serif;
  --font-mono: ui-monospace, 'Cascadia Code', 'Consolas', monospace;

  --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
  --text-sm: clamp(0.875rem, 0.8rem + 0.35vw, 1rem);
  --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.5rem);
  --text-xl: clamp(1.5rem, 1.2rem + 1.25vw, 2.25rem);
  --text-2xl: clamp(2rem, 1.2rem + 2.5vw, 3.5rem);

  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;

  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;

  --color-bg: #120F17;
  --color-surface: #17131d;
  --color-surface-2: #211b29;
  --color-card: #2F293A;
  --color-border: rgba(255,255,255,0.08);
  --color-text: #f5f1fb;
  --color-text-muted: #b3a9c4;
  /* Lightened from #746b84. The original scored 3.78:1 on the page
     background and 2.79:1 on card backgrounds — below the 4.5:1 WCAG AA
     minimum for small text, and .meta labels sit on cards. This value
     clears AA on all three surfaces. Revert if you prefer it dimmer. */
  --color-text-faint: #978eab;
  --color-primary: #8b7cf6;
  --color-primary-soft: rgba(139,124,246,0.14);

  /* Category accents — used by service cards and the network map. */
  --c-mgmt:  #8b7cf6;
  --c-mon:   #f6a97c;
  --c-media: #f67cc4;
  --c-prod:  #7cf6a5;
  --c-data:  #7cc4f6;
  --c-infra: #c47cf6;

  --shadow-lg: 0 20px 50px rgba(0,0,0,0.35);
  --max: 1120px;
}

/* ============================================================
   CROSS-DOCUMENT VIEW TRANSITIONS

   Makes clicking between pages cross-fade instead of hard-cutting,
   so a plain multi-page static site feels like an app. No JavaScript
   and no framework — the browser does it.

   Both pages must opt in, which happens automatically here because
   every page loads this one stylesheet.

   Pure progressive enhancement: browsers without support just
   navigate normally. Support is Chromium and Safari 18.2+, with
   Firefox arriving — so treat the animation as a bonus, never as
   something the site depends on.

   Note: the browser gives up if the next page is not ready within
   4 seconds, and fails silently when it does. Not a concern for
   static files on Cloudflare's edge, but it is why this is not
   worth using on a slow dynamic backend.
   ============================================================ */

@view-transition {
  navigation: auto;
}

/* The header is the same on every page, so give it a name and the
   browser will carry it across rather than fading it out and back in.
   That is what makes navigation feel continuous rather than like a
   page load. Each name must be unique within a page — there is only
   ever one header, so this is safe. */
.site-header { view-transition-name: site-header; }

/* Slightly slower than the 250ms default; the palette here is dark and
   a fast cross-fade on dark backgrounds reads as a flicker. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 320ms;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;

  /* WCAG 2.2 — 2.4.11 Focus Not Obscured.
     The header is sticky and 73px tall, so anything scrolled to — a skip-link
     target, an #anchor, or an element receiving keyboard focus — would land
     underneath it and be invisible. Reserving space here fixes all three at
     once. Particularly worth having because the skip link exists precisely
     for keyboard users, and without this it delivered them somewhere they
     could not see. */
  scroll-padding-top: 6rem;
}

body {
  min-height: 100vh;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--color-text);
  background:
    radial-gradient(circle at top left, rgba(139,124,246,0.12), transparent 30%),
    radial-gradient(circle at 85% 15%, rgba(255,255,255,0.05), transparent 18%),
    var(--color-bg);
}

/* ---------- Typography refinements ----------
   balance: evens out the line lengths of a heading, so you never get a
   headline with four words on line one and a single orphan on line two.
   Capped by browsers at ~6 lines, so it costs nothing on long text.
   Supported in Chrome, Edge, Firefox and Safari.

   pretty: stops a single short word being stranded alone on the last line
   of a paragraph. Firefox ignores it for now and simply wraps normally —
   no breakage, just no improvement there yet. */

h1, h2, h3,
.service-name,
.link-card strong,
.dropdown-title strong,
.stat-label { text-wrap: balance; }

p, .lede, .dropdown-summary, .section-note { text-wrap: pretty; }

a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
code { font-family: var(--font-mono); font-size: 0.9em; }

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

.container { width: min(calc(100% - 2rem), var(--max)); margin: 0 auto; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--color-primary);
  color: #14101c;
  padding: var(--space-3) var(--space-4);
  z-index: 100;
  border-radius: 0 0 var(--radius-md) 0;
  font-weight: 700;
}
.skip-link:focus { left: 0; }

/* ============================================================
   HEADER + NAV
   ============================================================ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  backdrop-filter: blur(14px);
  background: rgba(18, 15, 23, 0.78);
  border-bottom: 1px solid rgba(255,255,255,0.05);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  flex: 0 0 auto;
}

.brand:hover { color: var(--color-text); }

.mark {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: linear-gradient(180deg, rgba(139,124,246,0.22), rgba(139,124,246,0.08));
  border: 1px solid rgba(139,124,246,0.28);
  color: #d7d0ff;
  flex: 0 0 auto;
}

.header-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-wrap: wrap;
}

.nav-link {
  padding: 0.6rem 0.85rem;
  border-radius: 999px;
  color: var(--color-text-muted);
  border: 1px solid transparent;
  font-size: var(--text-sm);
  white-space: nowrap;
  transition: color 140ms ease, background 140ms ease, border-color 140ms ease;
}

.nav-link:hover {
  color: var(--color-text);
  background: rgba(255,255,255,0.03);
  border-color: var(--color-border);
}

.nav-link.active {
  color: var(--color-text);
  background: var(--color-primary-soft);
  border-color: rgba(139,124,246,0.28);
}

.nav-link.locked::after {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-left: 0.45rem;
  border-radius: 999px;
  background: var(--color-primary);
  vertical-align: middle;
}

/* Command palette trigger */
.palette-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  color: var(--color-text-faint);
  font-size: var(--text-xs);
  transition: color 140ms ease, border-color 140ms ease;
}

.palette-btn:hover { color: var(--color-text); border-color: rgba(139,124,246,0.4); }

.palette-btn kbd {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.08);
}

/* Mobile menu button — hidden on desktop */
.nav-toggle {
  display: none;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  place-items: center;
}

.nav-toggle:hover { color: var(--color-text); }

/* ============================================================
   HERO + SECTIONS
   ============================================================ */

.hero { padding: clamp(3.5rem, 9vw, 7rem) 0 var(--space-12); }

.hero-grid {
  display: grid;
  grid-template-columns: 1.25fr 0.95fr;
  gap: var(--space-10);
  align-items: end;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin-bottom: var(--space-6);
}

.eyebrow::before {
  content: "";
  width: 34px;
  height: 1px;
  background: rgba(139,124,246,0.9);
}

h1 {
  font-family: var(--font-display);
  font-size: clamp(3rem, 6vw, 5.2rem);
  line-height: 0.96;
  letter-spacing: -0.05em;
  max-width: 11ch;
  margin-bottom: var(--space-6);
}

h1.h1-compact {
  font-size: var(--text-2xl);
  line-height: 1.05;
  letter-spacing: -0.04em;
  max-width: 22ch;
}

.hero-copy p { color: var(--color-text-muted); max-width: 62ch; }

.lede { color: var(--color-text-muted); max-width: 62ch; }

.hero-panel {
  background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.015));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-8);
  box-shadow: var(--shadow-lg);
}

.hero-panel-label,
.section-kicker,
.meta {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.hero-panel-label,
.meta { color: var(--color-text-faint); }
.section-kicker { color: #cfc6ff; }

.hero-panel strong {
  display: block;
  font-size: var(--text-lg);
  margin: var(--space-3) 0;
}

.hero-panel p,
.section-note,
.overview-main p,
.overview-side p,
.overview-side li { color: var(--color-text-muted); }

/* ---------- Hero diagram ----------
   A small picture of the lab. Decorative, but accurate: three tiers, and the
   eighteen blocks are coloured by the same category palette the Services page
   uses, so the colours mean the same thing in both places. */

.lab-viz {
  width: 100%;
  height: auto;
  margin: var(--space-5) 0 var(--space-4);
}

.viz-links path,
.viz-pulse {
  fill: none;
  stroke: rgba(255,255,255,0.14);
  stroke-width: 1.2;
}

.viz-pulse {
  stroke: var(--color-primary);
  stroke-width: 1.6;
  stroke-dasharray: 26 320;
  stroke-linecap: round;
  animation: viz-travel 4.5s cubic-bezier(0.55, 0, 0.45, 1) infinite;
  opacity: 0.85;
}

@keyframes viz-travel {
  0%   { stroke-dashoffset: 346; opacity: 0; }
  12%  { opacity: 0.85; }
  80%  { opacity: 0.85; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}

.viz-node rect {
  fill: rgba(255,255,255,0.035);
  stroke: rgba(255,255,255,0.12);
  stroke-width: 1;
}

.viz-node.is-primary rect {
  fill: rgba(139,124,246,0.12);
  stroke: rgba(139,124,246,0.42);
}

.viz-node text {
  fill: var(--color-text);
  font-family: var(--font-body);
  font-size: 9.5px;
  text-anchor: middle;
  letter-spacing: 0.02em;
}

.viz-node .viz-sub {
  fill: var(--color-text-muted);
  font-size: 7.5px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.viz-tray {
  fill: rgba(255,255,255,0.025);
  stroke: rgba(255,255,255,0.09);
  stroke-width: 1;
}

.viz-tray-label {
  fill: var(--color-text-muted);
  font-family: var(--font-mono);
  font-size: 7.5px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

/* Blocks breathe gently, staggered, so it reads as running rather than static. */
.viz-cells rect {
  opacity: 0.5;
  animation: viz-breathe 3.6s ease-in-out infinite;
}

.viz-cells rect:nth-child(3n)   { animation-delay: 0.5s; }
.viz-cells rect:nth-child(3n+1) { animation-delay: 1.1s; }
.viz-cells rect:nth-child(5n)   { animation-delay: 1.7s; }
.viz-cells rect:nth-child(7n)   { animation-delay: 2.3s; }

@keyframes viz-breathe {
  0%, 100% { opacity: 0.42; }
  50%      { opacity: 0.92; }
}

.viz-cells .c-mgmt  { fill: var(--c-mgmt); }
.viz-cells .c-mon   { fill: var(--c-mon); }
.viz-cells .c-media { fill: var(--c-media); }
.viz-cells .c-prod  { fill: var(--c-prod); }
.viz-cells .c-data  { fill: var(--c-data); }

.viz-caption {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* The SVG scales down with the panel, and so does its text. On a phone the
   panel is ~277px wide, which rendered these labels at 6.9px — technically
   present, practically unreadable. Sizes are in viewBox units, so bumping
   them here restores roughly 11px on screen. */
@media (max-width: 600px) {
  .viz-node text { font-size: 12px; }
  .viz-node .viz-sub { font-size: 9.5px; }
  .viz-tray-label { font-size: 9.5px; letter-spacing: 0.08em; }
}

/* Motion is decorative here — hold it still if asked. */
@media (prefers-reduced-motion: reduce) {
  .viz-pulse { animation: none; opacity: 0.55; stroke-dasharray: none; }
  .viz-cells rect { animation: none; opacity: 0.7; }
}

.section { padding: var(--space-12) 0; }

.section-head {
  display: grid;
  gap: var(--space-3);
  margin-bottom: var(--space-8);
}

h2 {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  letter-spacing: -0.03em;
}

h3 {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  letter-spacing: -0.02em;
}

/* Buttons */
.btn-row { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-8); }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1.15rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  transition: all 160ms ease;
}

.btn:hover { color: var(--color-text); border-color: rgba(139,124,246,0.4); }

.btn-primary {
  background: var(--color-primary-soft);
  border-color: rgba(139,124,246,0.35);
  color: var(--color-text);
}

.btn-primary:hover { background: rgba(139,124,246,0.22); }

/* ============================================================
   OVERVIEW PANELS
   ============================================================ */

.overview {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: var(--space-6);
}

.overview-main,
.overview-side {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-8);
}

.stack-list {
  list-style: none;
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.stack-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  padding-bottom: var(--space-3);
}

.stack-list span:last-child {
  text-align: right;
  color: var(--color-text);
}

/* ============================================================
   STAT TILES
   ============================================================ */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-4);
}

.stat {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
}

.stat-value {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 2.75rem);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--color-text);
  display: block;
}

.stat-label {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-faint);
}

/* ============================================================
   ACCORDION CARDS
   ============================================================ */

.hardware-stack { display: grid; gap: 1.25rem; }

.item {
  padding: 20px 22px;
  background-color: var(--color-card);
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.04);
  box-shadow: 0 10px 24px rgba(0,0,0,0.16);
}

/* The accordion header is a <summary>. Removing the default disclosure
   triangle needs both of these: list-style for Chromium and Firefox, and the
   -webkit- pseudo-element for Safari, which still uses its own marker. */
.dropdown {
  width: 100%;
  text-align: left;
  display: grid;
  gap: var(--space-2);
  padding: 0;
  cursor: pointer;
  list-style: none;
}

.dropdown::-webkit-details-marker { display: none; }

/* summary is a phrasing-content container, so its children are spans.
   These restore the block/flex behaviour the old divs had. */
.dropdown-head { display: flex; }
.dropdown-title { display: grid; }
.dropdown .meta,
.dropdown-summary { display: block; }

.dropdown-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.dropdown-title { display: grid; gap: 0.35rem; }

.dropdown-title strong {
  font-size: var(--text-lg);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--color-text);
}

.dropdown-title span,
.dropdown-summary,
.dropdown-content p,
.dropdown-content li { color: var(--color-text-muted); }

.dropdown-icon {
  width: 38px;
  height: 38px;
  flex: 0 0 auto;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.05);
  transition: transform 180ms ease;
}

/* [open] is the native <details> state, set by the browser. */
.item[open] .dropdown-icon { transform: rotate(180deg); }

.dropdown-summary { margin-top: var(--space-2); }

.dropdown-content {
  padding-top: var(--space-4);
  margin-top: var(--space-5);
  border-top: 1px solid rgba(255,255,255,0.06);
}

/* Nothing needed here any more. Native <details> shows and hides its own
   content, so there is no display rule to write and no no-JS guard to
   maintain — the panels work with scripting switched off. */

/* A chevron implies something is collapsible. Without JS nothing is. */
html:not(.js) .dropdown-icon { display: none; }
html:not(.js) .dropdown { cursor: default; }

.product-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: var(--space-5);
  margin-right: var(--space-5);
  color: #ddd6ff;
  font-size: var(--text-sm);
}

.product-link:hover { color: #ffffff; }
.product-link svg { opacity: 0.8; }

.specs {
  list-style: none;
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.specs li {
  padding-top: var(--space-2);
  border-top: 1px solid rgba(255,255,255,0.06);
}

/* ============================================================
   SERVICE GRID + FILTERING
   ============================================================ */

.filter-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-6);
}

.search-field {
  position: relative;
  flex: 1 1 240px;
  min-width: 0;
}

.search-field input {
  width: 100%;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.65rem 1rem 0.65rem 2.4rem;
}

.search-field input::placeholder { color: var(--color-text-faint); }
.search-field input:focus { outline: none; border-color: rgba(139,124,246,0.45); }

.search-field svg {
  position: absolute;
  left: 0.85rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-faint);
  pointer-events: none;
}

.chips { display: flex; gap: 0.4rem; flex-wrap: wrap; }

.chip {
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  transition: all 140ms ease;
}

.chip:hover { color: var(--color-text); border-color: rgba(255,255,255,0.2); }

.chip[aria-pressed="true"] {
  color: var(--color-text);
  background: var(--color-primary-soft);
  border-color: rgba(139,124,246,0.4);
}

.service-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--space-4);
}

.service {
  position: relative;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  overflow: hidden;
  transition: border-color 160ms ease, transform 160ms ease;
}

.service::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--accent, var(--color-primary));
  opacity: 0.8;
}

.service:hover { border-color: rgba(255,255,255,0.18); transform: translateY(-2px); }

.service[hidden] { display: none; }

/* Per-category accent, used by the left edge stripe and the label. */
.service[data-category="mgmt"]  { --accent: var(--c-mgmt); }
.service[data-category="mon"]   { --accent: var(--c-mon); }
.service[data-category="media"] { --accent: var(--c-media); }
.service[data-category="prod"]  { --accent: var(--c-prod); }
.service[data-category="data"]  { --accent: var(--c-data); }
.service[data-category="infra"] { --accent: var(--c-infra); }

.service-name {
  font-family: var(--font-display);
  font-size: var(--text-base);
  letter-spacing: -0.01em;
  color: var(--color-text);
  margin-bottom: 0.3rem;
}

.service-cat {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent, var(--color-primary));
  margin-bottom: var(--space-3);
  display: block;
}

.service p { font-size: var(--text-sm); color: var(--color-text-muted); }

.empty-state {
  padding: var(--space-10);
  text-align: center;
  color: var(--color-text-faint);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-xl);
}

/* ============================================================
   NETWORK MAP (inline SVG)
   ============================================================ */

.map-wrap {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-4);
  overflow-x: auto;
}

.map-wrap svg { width: 100%; min-width: 760px; height: auto; }

.map-node { cursor: pointer; }

.map-node rect {
  fill: var(--color-card);
  stroke: rgba(255,255,255,0.1);
  stroke-width: 1;
  transition: stroke 160ms ease, fill 160ms ease;
}

.map-node:hover rect,
.map-node.selected rect {
  stroke: var(--node-accent, var(--color-primary));
  fill: #362f45;
}

/* Keyboard focus on the map.
   The global :focus-visible outline does not render reliably on an SVG <g>,
   so the indicator is drawn as a stroke on the rect instead. Dashed, so it
   stays distinguishable from the solid stroke that marks the selected node —
   a keyboard user needs to see both states at once. */
.map-node:focus { outline: none; }

.map-node:focus-visible rect {
  stroke: var(--color-text);
  stroke-width: 2.5;
  stroke-dasharray: 5 3;
}

.map-node text { fill: var(--color-text); font-size: 13px; font-family: var(--font-body); }
/* Muted rather than faint: at 10.5px on the card fill, faint was unreadable. */
.map-node .map-sub { fill: var(--color-text-muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.08em; }
.map-link {
  stroke: rgba(255,255,255,0.16);
  stroke-width: 1.5;
  fill: none;
  transition: stroke 180ms ease, stroke-width 180ms ease, opacity 180ms ease;
}
.map-link.dashed { stroke-dasharray: 4 4; }

/* Connections of the selected node. */
.map-link.active { stroke: var(--color-primary); stroke-width: 2.2; opacity: 1; }
.map-link.dimmed { opacity: 0.3; }

@media (prefers-reduced-motion: reduce) {
  .map-link { transition: none; }
}
.map-zone { fill: rgba(255,255,255,0.02); stroke: rgba(255,255,255,0.07); stroke-dasharray: 3 4; }
.map-zone-label { fill: var(--color-text-faint); font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; }

/* Key for the diagram. The dashed line in particular means something
   specific — storage, not network — and nothing else on the page said so. */
.map-legend {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin-top: var(--space-4);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.map-legend li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.legend-line {
  width: 26px;
  height: 0;
  flex: 0 0 auto;
  /* Slightly stronger than the real links: at 26px a 0.16 alpha stroke
     is invisible, and a key nobody can see is worse than no key. */
  border-top: 2px solid rgba(255,255,255,0.3);
}

.legend-line.is-dashed { border-top-style: dashed; }

.legend-line.is-active {
  border-top-color: var(--color-primary);
  border-top-width: 2.5px;
}

.map-detail {
  margin-top: var(--space-4);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  min-height: 120px;
}

.map-detail h3 { margin-bottom: var(--space-2); }
.map-detail p { color: var(--color-text-muted); font-size: var(--text-sm); }
.map-detail ul { list-style: none; margin-top: var(--space-3); display: grid; gap: var(--space-2); }
.map-detail li {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  padding-top: var(--space-2);
  border-top: 1px solid rgba(255,255,255,0.06);
}

/* ============================================================
   COMMAND PALETTE
   ============================================================ */

/* Native <dialog>. Opened with showModal() it lives in the browser's top
   layer, so it needs no z-index and cannot be trapped under a stacking
   context. These rules mostly undo the user-agent defaults, which centre a
   dialog in a small box — here it should fill the viewport. */
.palette {
  position: fixed;
  inset: 0;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;
  border: 0;
  padding: 12vh var(--space-4) var(--space-4);
  background: transparent;
  color: inherit;
  overflow-y: auto;
}

/* The dimmed layer behind a modal dialog is its own pseudo-element rather
   than a background on the dialog itself. */
.palette::backdrop {
  background: rgba(9, 7, 12, 0.72);
  backdrop-filter: blur(6px);
}

.palette-box {
  max-width: 560px;
  margin: 0 auto;
  background: var(--color-surface);
  border: 1px solid rgba(139,124,246,0.25);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.palette-box input {
  width: 100%;
  font: inherit;
  color: var(--color-text);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-5) var(--space-6);
}

.palette-box input:focus { outline: none; }
.palette-box input::placeholder { color: var(--color-text-faint); }

.palette-results { max-height: 44vh; overflow-y: auto; padding: var(--space-2); }

.palette-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.palette-item:hover,
.palette-item.active {
  background: var(--color-primary-soft);
  color: var(--color-text);
}

.palette-item .palette-tag {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-text-faint);
  flex: 0 0 auto;
}

.palette-empty { padding: var(--space-6); text-align: center; color: var(--color-text-faint); font-size: var(--text-sm); }

/* ============================================================
   PRIVATE AREA
   ============================================================ */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: var(--space-4);
}

.link-card {
  display: block;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  transition: border-color 160ms ease, transform 160ms ease;
}

.link-card:hover {
  border-color: rgba(139,124,246,0.35);
  transform: translateY(-2px);
}

.link-card strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  letter-spacing: -0.02em;
  margin: var(--space-2) 0;
}

.link-card p { color: var(--color-text-muted); font-size: var(--text-sm); }

/* Address rows with copy buttons */
.addr-table { display: grid; gap: var(--space-2); }

.addr-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  flex-wrap: wrap;
}

.addr-name { flex: 1 1 160px; font-size: var(--text-sm); }
.addr-name small { display: block; color: var(--color-text-faint); font-size: var(--text-xs); }

.addr-value {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  background: rgba(255,255,255,0.04);
  border-radius: 6px;
  padding: 0.25rem 0.5rem;
}

.copy-btn {
  font-size: var(--text-xs);
  color: var(--color-text-faint);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
  transition: all 140ms ease;
  flex: 0 0 auto;
}

.copy-btn:hover { color: var(--color-text); border-color: rgba(139,124,246,0.4); }
.copy-btn.done { color: var(--c-prod); border-color: rgba(124,246,165,0.4); }

.embed-frame {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-4);
  min-height: 640px;
  overflow: hidden;
}

/* ============================================================
   NOTES / CALLOUTS
   ============================================================ */

.note {
  border-left: 3px solid #d9a441;
  background: rgba(217,164,65,0.07);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-6);
  font-size: var(--text-sm);
  color: #e2b95f;
}

.note strong { color: #f2cf80; }

.note-info {
  border-left-color: var(--color-primary);
  background: var(--color-primary-soft);
  color: #cfc6ff;
}
.note-info strong { color: #e2dcff; }

/* ============================================================
   FOOTER
   ============================================================ */

.footer {
  padding: var(--space-12) 0 var(--space-16);
  color: var(--color-text-faint);
  font-size: var(--text-sm);
  border-top: 1px solid rgba(255,255,255,0.05);
  margin-top: var(--space-12);
}

.footer-inner {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

/* WCAG 2.2 — 2.5.8 Target Size (Minimum).
   The footer link measured 78x19, under the 24px minimum height. It would
   probably scrape through on the spacing exception, since nothing sits near
   it, but relying on that to justify a fiddly tap target is the wrong call —
   it costs one line to just make it comfortable. */
.footer a {
  display: inline-block;
  padding-block: 0.2rem;
  min-height: 24px;
}

.footer a:hover { color: var(--color-text-muted); }

/* ============================================================
   SCROLL REVEAL
   ============================================================ */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 500ms ease, transform 500ms ease;
}

.reveal.shown { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }

  /* The universal rule above does not reach view-transition pseudo-elements —
     they live outside the normal tree — so they need naming explicitly.
     Navigation still works; it just cuts instead of animating. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 900px) {
  .hero-grid,
  .overview { grid-template-columns: 1fr; }
  .hero { padding-top: var(--space-12); }
  h1 { max-width: 12ch; }
  .stack-list li { flex-direction: column; gap: 0.35rem; }
  .stack-list span:last-child { text-align: left; }
}

/* Nav collapses at the same width the grids do.
   These used to be 760px and 900px. In the gap between them the full nav was
   shown but wrapped onto three rows, giving a 129px sticky header on a tablet.
   One breakpoint avoids that entirely. */
@media (max-width: 900px) {
  /* Same reasoning as the accordions: without JS the toggle button does
     nothing, so it stays hidden and the nav renders inline instead. A
     wrapped nav is ugly; no nav at all is broken. */
  .js .nav-toggle { display: grid; }

  .js .site-nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--space-3);
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    box-shadow: var(--shadow-lg);
  }

  .js .site-nav.open { display: flex; }

  .nav-link {
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
  }

  .site-header { position: sticky; }
  .header-inner { position: relative; }
}

/* The palette button survives longer than the nav — it is only 122px wide and
   still useful on a keyboard-equipped tablet. Ctrl+K works regardless. */
@media (max-width: 600px) {
  .palette-btn { display: none; }
}

@media (max-width: 480px) {
  .service-grid { grid-template-columns: 1fr; }
  .stats { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================================
   PRINT
   Mainly for the runbooks page — if the network is what's broken,
   a printed or PDF'd copy is worth having. The important rule is
   forcing the accordions open: they are collapsed by default, so
   without this you would print six headings and no content.
   ============================================================ */

@media print {
  .site-header,
  .palette,
  .nav-toggle,
  .palette-btn,
  .skip-link,
  .filter-bar,
  .btn-row,
  .copy-btn,
  .empty-state { display: none !important; }

  body {
    background: #fff;
    color: #000;
    font-size: 11pt;
  }

  .container { width: 100%; max-width: none; padding: 0; }

  main { padding: 0; }
  .hero { padding: 0 0 1rem; }
  .section { padding: 0.75rem 0; page-break-inside: avoid; }

  h1, h1.h1-compact { font-size: 20pt; max-width: none; margin-bottom: 0.4rem; }
  h2 { font-size: 14pt; }
  h3 { font-size: 12pt; }

  /* Every accordion prints fully open. */
  .dropdown-content { display: block !important; }
  .dropdown-icon { display: none; }
  .item {
    background: #fff;
    border: 1px solid #999;
    box-shadow: none;
    page-break-inside: avoid;
    margin-bottom: 0.5rem;
  }

  .hero-panel,
  .overview-main,
  .overview-side,
  .stat,
  .service,
  .link-card,
  .addr-row,
  .map-detail,
  .map-wrap {
    background: #fff;
    border: 1px solid #999;
    box-shadow: none;
    page-break-inside: avoid;
  }

  .eyebrow,
  .section-kicker,
  .meta,
  .lede,
  p, li, dd, dt,
  .dropdown-title strong,
  .dropdown-summary,
  .service p,
  .addr-name { color: #000 !important; }

  .addr-value { background: #eee; color: #000; }

  .note {
    border-left: 3px solid #666;
    background: #f4f4f4;
    color: #000;
  }
  .note strong { color: #000; }

  a { color: #000; text-decoration: underline; }

  .reveal { opacity: 1 !important; transform: none !important; }

  .footer { border-top: 1px solid #999; color: #000; }
}
