/* ==========================================================================
   Billing Transfer Simulator — AWS Console (Cloudscape) light theme.

   Design language: Minimalism / Swiss — white surfaces, near-black text,
   crisp 1px dividers, a single blue action colour, and no decoration that
   isn't carrying information. Token names and values mirror the Cloudscape
   Design System so the simulator reads as part of the AWS Console.
   ========================================================================== */

:root {
  /* --- Surfaces ---------------------------------------------------------- */
  --bg-page: #ffffff;
  --bg-layout: #f9f9fa;          /* page canvas behind containers */
  --bg-container: #ffffff;
  --bg-subtle: #f4f4f4;          /* input / inset fills */
  --bg-hover: #f2f8fd;           /* blue-tinted row hover */
  --bg-selected: #f0f7ff;

  /* --- Text ------------------------------------------------------------- */
  --text-heading: #0f141a;
  --text-body: #16191f;
  --text-secondary: #5f6b7a;
  --text-disabled: #9ba7b6;
  --text-inverse: #ffffff;

  /* --- Lines ------------------------------------------------------------ */
  --line-default: #c6c6cd;
  --line-subtle: #e9ebed;
  --line-strong: #7d8998;

  /* --- Action blue ------------------------------------------------------ */
  --blue: #006ce0;
  --blue-hover: #00437a;
  --blue-active: #002b66;
  --blue-subtle: #f0fbff;

  /* --- Status ----------------------------------------------------------- */
  --success: #00802f;
  --success-bg: #f2fcf3;
  --warning: #855900;
  --warning-bg: #fffce9;
  --error: #d91515;
  --error-bg: #fff7f7;
  --info: #006ce0;
  --info-bg: #f0fbff;

  /* --- Brand accent (used sparingly, AWS orange darkened for contrast) -- */
  --accent: #b25000;

  /* --- Radii (Cloudscape visual refresh) -------------------------------- */
  --r-container: 16px;
  --r-control: 8px;
  --r-button: 20px;
  --r-badge: 4px;

  /* --- Shadows ---------------------------------------------------------- */
  --shadow-container: 0 0 1px 1px var(--line-subtle), 0 1px 8px 2px rgba(0, 7, 22, 0.06);
  --shadow-raised: 0 1px 4px 0 rgba(0, 7, 22, 0.1), 0 4px 12px 0 rgba(0, 7, 22, 0.08);
  --shadow-drag: 0 6px 20px 0 rgba(0, 7, 22, 0.18);

  /* --- Density 8/10: dense dashboard spacing scale ---------------------- */
  --space-xxs: 2px;
  --space-xs: 4px;
  --space-s: 8px;
  --space-m: 12px;
  --space-l: 16px;
  --space-xl: 24px;
  --space-xxl: 32px;

  /* System fonts only: the site loads nothing from third-party hosts. */
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur: 180ms;

  --max-width: 1600px;
  /* Single horizontal gutter shared by every full-width band (nav, header,
     stepper, status, columns, log) so their edges line up exactly. */
  --gutter: var(--space-xl);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg-layout);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Visible focus ring on every interactive element — never removed. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
  border-radius: var(--r-badge);
}

/* Screen-reader-only helper for labels we don't want painted. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.icon { flex: 0 0 auto; display: block; }

/* Official AWS Architecture Icons (see assets/icons/README.md and ui/awsIcons.js).
   Rendered as <img> from the pack's unmodified SVGs, so there is deliberately no
   `color`, `fill` or `filter` here — the artwork keeps its own AWS colours and
   the surrounding role tint lives on borders and text instead. Width/height come
   from the markup so the box is reserved before the file loads. */
.aws-icon { flex: 0 0 auto; display: block; }

/* A rounded plate that a thin line-art icon sits on (see awsIconPlate in
   ui/awsIcons.js, which decides which icons get one). The resource icons are line
   art in a 48px frame, so at 16-20px they leave under a pixel of ink and wash
   out. The fix cannot touch the artwork, so the weight goes behind it: a tint
   wash with a hairline edge, which also gives the line art the same squircle
   silhouette the solid service tiles already have. --tint is the role colour
   where the surrounding block sets one; grey otherwise, so a plate in the
   Resources panel stays neutral chrome. The box comes in as an inline --plate so
   the radius stays derived from it; 24px is only the fallback. */
.icon-plate {
  --plate: 24px;
  --plate-tint: var(--tint, #7d8998);
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: var(--plate);
  height: var(--plate);
  border-radius: calc(var(--plate) / 4);
  background: color-mix(in srgb, var(--plate-tint) 10%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--plate-tint) 24%, #fff);
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* ==========================================================================
   Top navigation
   ========================================================================== */

.top-nav {
  position: sticky; top: 0; z-index: 900;
  background: var(--bg-container);
  border-bottom: 1px solid var(--line-subtle);
}
.top-nav-inner {
  max-width: var(--max-width); margin: 0 auto;
  height: 44px; padding: 0 var(--gutter);
  display: flex; align-items: center; gap: var(--space-m);
}
.brand { display: flex; align-items: center; gap: var(--space-s); min-width: 0; }
/* Official AWS mark from the Architecture Icons pack (see assets/icons/README.md).
   The artwork already carries its own dark plate, so no background here. */
.brand-mark {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  border-radius: var(--r-badge);
  display: block;
}
.brand-name {
  font-weight: 700; font-size: 14px; color: var(--text-heading);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.top-nav-divider { flex: 0 0 1px; align-self: stretch; margin: 10px 0; background: var(--line-subtle); }
.top-nav-service {
  font-size: 14px; color: var(--text-body); min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.top-nav .badge.scenario-chip { font-family: inherit; flex: 0 0 auto; }
.top-nav .scenario-chip:empty { display: none; }
.top-nav-actions { display: flex; align-items: center; gap: var(--space-xxs); min-width: 0; }
.top-nav-actions .btn { min-height: 28px; padding: 2px 8px; font-size: 13px; }
.top-nav-spacer { flex: 1 1 auto; }
.top-nav-meta {
  display: flex; align-items: center; gap: var(--space-xs);
  font-size: 12px; color: var(--text-secondary); font-family: var(--font-mono);
  white-space: nowrap;
}

/* ==========================================================================
   Flash notification (Cloudscape Flashbar)
   ========================================================================== */

.flashbar {
  position: fixed; top: 56px; left: 50%; z-index: 1000;
  width: min(720px, calc(100% - 28px));
  transform: translateX(-50%) translateY(-8px);
  display: flex; align-items: flex-start; gap: var(--space-s);
  padding: var(--space-m) var(--space-m) var(--space-m) var(--space-l);
  border: 1px solid var(--line-subtle); border-radius: var(--r-control);
  background: var(--bg-container); color: var(--text-body);
  box-shadow: var(--shadow-raised);
  font-size: 14px; opacity: 0;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.flashbar.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.flashbar::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  border-radius: var(--r-control) 0 0 var(--r-control); background: var(--error);
}
.flashbar .flash-icon { color: var(--error); margin-top: 2px; }
.flashbar .flash-text { flex: 1 1 auto; min-width: 0; }
.flashbar .flash-label { font-weight: 700; display: block; }
.flashbar.flash-success { background: var(--success-bg); }
.flashbar.flash-success::before { background: var(--success); }
.flashbar.flash-success .flash-icon { color: var(--success); }
.flashbar.flash-error { background: var(--error-bg); }
.flashbar.flash-info { background: var(--info-bg); }
.flashbar.flash-info::before { background: var(--info); }
.flashbar.flash-info .flash-icon { color: var(--info); }

.flash-dismiss {
  flex: 0 0 auto; border: none; background: transparent; cursor: pointer;
  color: var(--text-secondary); padding: 2px; border-radius: var(--r-badge);
  display: grid; place-items: center;
}
.flash-dismiss:hover { background: rgba(0, 7, 22, 0.06); color: var(--text-body); }

/* ==========================================================================
   Containers
   ========================================================================== */

.container {
  background: var(--bg-container);
  border-radius: var(--r-container);
  box-shadow: var(--shadow-container);
}
.container-header {
  padding: var(--space-m) var(--space-l);
  border-bottom: 1px solid var(--line-subtle);
  display: flex; align-items: baseline; gap: var(--space-s); flex-wrap: wrap;
}
.container-header h2 {
  margin: 0; font-size: 16px; font-weight: 700; color: var(--text-heading);
}
.container-header .counter { font-size: 14px; font-weight: 400; color: var(--text-secondary); }
.container-header .header-desc-inline { margin-left: auto; font-size: 12px; color: var(--text-secondary); }
.container-header .header-desc {
  flex: 1 1 100%; margin: var(--space-xxs) 0 0; font-size: 12px; color: var(--text-secondary);
}
/* Header-level actions sit flush right, the way console containers place them. */
.container-header .header-actions {
  margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--space-s); align-items: center;
}
.container-body { padding: var(--space-l); }
.container-body.flush { padding: 0; }

/* A flex row so a section heading can lead with its AWS service icon. Headings
   without one are unaffected — a single text node still lays out identically. */
.section-label {
  display: flex; align-items: center; gap: var(--space-s);
  font-size: 12px; font-weight: 700; color: var(--text-heading);
  letter-spacing: 0.2px;
  margin: 0 0 var(--space-s);
}
/* Sits directly under a .section-label to say which AWS console a group of
   actions belongs to. The label's own bottom margin collapses away so heading and
   note read as one unit, keeping the divider above them the clear break between
   two different consoles. */
.section-desc {
  font-size: 12px; color: var(--text-secondary); line-height: 1.4;
  margin: calc(-1 * var(--space-xs)) 0 var(--space-m);
}
.hint { font-size: 12px; color: var(--text-secondary); margin: 0; }
.divider { height: 1px; background: var(--line-subtle); border: 0; margin: var(--space-l) 0; }

/* ==========================================================================
   Wizard stepper (stage tracker)
   ========================================================================== */

/* #hud owns the page gutter so the status bar aligns with the columns below.
   Stepper, scoreboard and run controls share one container to keep the board
   high on the first screen. */
#hud {
  max-width: var(--max-width); margin: var(--space-l) auto;
  padding: 0 var(--gutter);
}
.hud-bar { overflow: hidden; }
.stepper { border-bottom: 1px solid var(--line-subtle); }
.stepper-track {
  display: flex; align-items: flex-start;
  margin: 0; padding: var(--space-m) var(--space-l);
  list-style: none;
  overflow-x: auto;
}
/* Steps size to their label and never clip; the connecting rules absorb all the
   slack, and the track scrolls sideways when there is none left. */
.step { display: flex; align-items: flex-start; gap: var(--space-s); flex: 0 0 auto; }
.step-marker {
  flex: 0 0 auto; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  border: 1px solid var(--line-default); background: var(--bg-container); color: var(--text-secondary);
}
.step-text { padding-top: 1px; }
.step-name {
  display: block;
  font-size: 13px; font-weight: 600; color: var(--text-secondary);
  white-space: nowrap;
}
.step-state { display: block; font-size: 11px; color: var(--text-disabled); }
.step-line {
  flex: 1 1 auto; height: 1px; min-width: 16px; margin: 12px var(--space-s) 0;
  background: var(--line-subtle);
}

.step.complete .step-marker { background: var(--success); border-color: var(--success); color: #fff; }
.step.complete .step-name { color: var(--text-heading); }
.step.complete .step-state { color: var(--success); }
.step.complete + .step-line { background: var(--success); }
.step.available .step-marker { border-color: var(--blue); border-width: 2px; color: var(--blue); }
.step.available .step-name { color: var(--text-heading); }
.step.available .step-state { color: var(--blue); }
.step.locked .step-marker { color: var(--text-disabled); }
/* A stage completed by the last action: the check pops in. */
.step.just-completed .step-marker { animation: step-pop 700ms var(--ease) both; }
@keyframes step-pop {
  0% { transform: scale(0.6); box-shadow: 0 0 0 0 rgba(0, 128, 47, 0.5); }
  50% { transform: scale(1.2); }
  100% { transform: scale(1); box-shadow: 0 0 0 10px rgba(0, 128, 47, 0); }
}

/* ==========================================================================
   Stat tiles — the run's scoreboard. One box per metric, each carrying a top
   accent rule in its own colour (the same idiom the board nodes use) so the
   readout scans like a game HUD without leaving the console palette.
   ========================================================================== */

.hud-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-m) var(--space-l);
  padding: var(--space-s) var(--space-l);
}
.stat-strip {
  display: flex; flex-wrap: wrap; align-items: stretch;
  gap: var(--space-s) var(--space-l);
  flex: 0 1 auto; min-width: 0;
}
.stat-tile {
  --tone: var(--line-strong);
  display: flex; flex-direction: column; justify-content: center;
  padding: 0 0 0 var(--space-s);
  border-left: 3px solid var(--tone);
}
.stat-head {
  display: flex; align-items: center; gap: var(--space-xs);
  color: var(--tone);
}
.stat-head .icon { width: 12px; height: 12px; flex: 0 0 auto; }
.stat-label {
  font-size: 10px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase;
  color: var(--text-secondary); white-space: nowrap;
}
.stat-value {
  font-size: 17px; font-weight: 700; line-height: 1.25;
  color: var(--text-heading);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Tones. Idle stays grey so a clean run does not look like a warning. */
.stat-note { font-size: 12px; font-weight: 400; color: var(--text-secondary); font-family: var(--font-body); letter-spacing: 0; }
.stat-tile.tone-clock { --tone: var(--accent); }
.stat-tile.tone-clock .stat-value { font-family: var(--font-mono); letter-spacing: 0.5px; }
.stat-tile.tone-score { --tone: var(--blue); }
.stat-tile.tone-score .stat-value { color: var(--blue); }
.stat-tile.tone-idle { --tone: var(--line-default); }
.stat-tile.tone-idle .stat-value { color: var(--text-secondary); }
.stat-tile.tone-warn { --tone: var(--warning); }
.stat-tile.tone-warn .stat-value { color: var(--warning); }
.stat-tile.tone-error { --tone: var(--error); }
.stat-tile.tone-error .stat-value { color: var(--error); }
.stat-tile.tone-done { --tone: var(--success); }
.stat-tile.tone-done .stat-value { color: var(--success); }

/* One-shot feedback: the month flips, the score floats its delta. */
.stat-tile { position: relative; }
.stat-tile.tick .stat-value { animation: month-flip 520ms var(--ease) both; }
@keyframes month-flip {
  0% { transform: rotateX(90deg); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
.score-delta {
  position: absolute; right: -14px; top: -6px;
  font-size: 13px; font-weight: 700; white-space: nowrap; pointer-events: none;
  animation: score-float 1400ms var(--ease) both;
}
.score-delta.up { color: var(--success); }
.score-delta.down { color: var(--error); }
@keyframes score-float {
  0% { opacity: 0; transform: translateY(6px); }
  15% { opacity: 1; transform: none; }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-10px); }
}
.hud-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs); margin-left: auto; }
.hud-actions .btn-primary { margin-left: var(--space-s); }
.kv .kv-value.muted { color: var(--text-secondary); font-weight: 600; font-size: 14px; }

/* Status indicator (icon + label) */
.status { display: inline-flex; align-items: center; gap: var(--space-xs); font-size: 14px; font-weight: 400; }
.status .icon { width: 15px; height: 15px; }
.status-success { color: var(--success); }
.status-error { color: var(--error); }
.status-warning { color: var(--warning); }
.status-info, .status-pending { color: var(--text-secondary); }

/* Objective alert */
.alert {
  display: flex; gap: var(--space-s); align-items: flex-start;
  margin: 0 var(--space-l) var(--space-m); padding: var(--space-m);
  border: 1px solid var(--line-subtle); border-radius: var(--r-control);
  font-size: 14px;
}
.alert-success { background: var(--success-bg); border-color: #b7f0bf; align-items: center; }
.alert > .btn { margin-left: auto; }
.alert-success .icon { color: var(--success); margin-top: 2px; }
.alert strong { color: var(--text-heading); }
.alert .chain { font-family: var(--font-mono); font-size: 13px; }

/* ==========================================================================
   Buttons (Cloudscape: pill radius, 32px min height)
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-xs);
  min-height: 32px; padding: 4px 20px;
  border-radius: var(--r-button); border: 2px solid transparent;
  font-family: inherit; font-size: 14px; font-weight: 700; line-height: 1.2;
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn .icon { width: 15px; height: 15px; flex: 0 0 auto; }
.btn-primary { background: var(--blue); border-color: var(--blue); color: var(--text-inverse); }
.btn-primary:hover { background: var(--blue-hover); border-color: var(--blue-hover); }
.btn-primary:active { background: var(--blue-active); border-color: var(--blue-active); }
.btn-normal { background: transparent; border-color: var(--blue); color: var(--blue); }
.btn-normal:hover { background: var(--bg-hover); border-color: var(--blue-hover); color: var(--blue-hover); }
.btn-link {
  background: transparent; border-color: transparent; color: var(--blue);
  padding: 4px 8px; font-weight: 400;
}
.btn-link:hover { background: var(--bg-hover); color: var(--blue-hover); text-decoration: underline; }
.btn-danger { background: transparent; border-color: var(--error); color: var(--error); }
.btn-danger:hover { background: var(--error-bg); }
.btn-small { min-height: 28px; padding: 2px 14px; font-size: 13px; }
.btn:disabled, .btn[aria-disabled="true"] {
  background: transparent; border-color: var(--text-disabled); color: var(--text-disabled);
  cursor: not-allowed;
}
.btn-primary:disabled { background: transparent; }

/* Full-width buttons live in the narrow side panels, where a centred nowrap pill
   label spills past its own border. These read as action rows instead: icon
   leading, label free to wrap, and the wide pill padding traded for the panel's
   own gutter. The control radius replaces the pill one because a wrapped label
   in a 20px-radius box reads as a stretched lozenge. */
.btn-full {
  width: 100%;
  justify-content: flex-start; text-align: left;
  padding: 7px var(--space-m);
  border-radius: var(--r-control);
  white-space: normal; line-height: 1.35;
}

/* Disclosure trigger: the chevron sits flush right and turns as the form opens,
   so the control reads as "reveal a form" rather than "add one immediately". */
.btn-disclosure .chevron {
  margin-left: auto; display: inline-flex;
  transition: transform var(--dur) var(--ease);
}
.btn-disclosure.is-open .chevron { transform: rotate(90deg); }

/* ==========================================================================
   App layout — left resources / board / right inspector
   ========================================================================== */

#app {
  display: grid;
  /* 280px is what the Resources panel needs to hold its action labels on one
     line; below that they wrap, which the buttons handle but reads busier. */
  grid-template-columns: 280px minmax(0, 1fr) 360px;
  gap: var(--space-l);
  max-width: var(--max-width); margin: 0 auto;
  padding: 0 var(--gutter);
  align-items: start;
}
/* The board column stretches with the row and the board itself takes up the
   slack, so neither column is left with dead space below it. */
.col-board { min-width: 0; align-self: stretch; display: flex; }
.col-board > .container { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.sidebar-left {
  position: sticky; top: 56px;
  max-height: calc(100vh - 72px); overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--space-l);
  /* Room for the containers' shadows inside the scroll box. */
  margin: -4px; padding: 4px;
}
/* The details panel stays put and scrolls internally instead of stretching the
   page — the board must remain visible while you configure a node. */
/* It spans the full row height so the column reads as a deliberate split panel
   rather than a small card floating above a void. */
.sidebar-right {
  position: sticky; top: 56px; align-self: stretch;
  max-height: calc(100vh - 72px); display: flex; flex-direction: column;
}
.sidebar-right > .container { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.sidebar-right .container-body { overflow-y: auto; min-height: 0; }

@media (max-width: 1280px) {
  #app { grid-template-columns: 248px minmax(0, 1fr); }
  .sidebar-right { grid-column: 1 / -1; position: static; max-height: none; }
}
@media (max-width: 900px) {
  :root { --gutter: var(--space-l); }
  #app { grid-template-columns: minmax(0, 1fr); }
  .sidebar-left { position: static; max-height: none; overflow: visible; }
  /* Stack the clock controls full width rather than pushing the page wider. */
  .hud-actions { margin-left: 0; flex: 1 1 100%; }
  .hud-actions .btn-primary { flex: 1 1 100%; margin-left: 0; }
  .container-header .header-desc-inline { display: none; }
  .step-line { min-width: 24px; }
  /* Drop the service name from the nav so the brand, scenario and sim clock
     all stay legible instead of overlapping. */
  .top-nav-divider, .top-nav-service { display: none; }
  /* Icon-only scenario controls; the label stays as the accessible name. */
  .top-nav-actions .btn span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}

/* ==========================================================================
   Next steps (left column, above Resources)
   ========================================================================== */

.guide-stage { margin: 0 0 var(--space-s); font-size: 13px; font-weight: 700; color: var(--blue); }
.guide-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.guide-row {
  display: flex; align-items: flex-start; gap: var(--space-s);
  width: 100%; padding: 5px var(--space-xs);
  border: 0; border-radius: var(--r-badge); background: transparent;
  font: inherit; font-size: 12.5px; line-height: 1.4; color: var(--text-secondary); text-align: left;
}
button.guide-row { cursor: pointer; transition: background-color var(--dur) var(--ease); }
button.guide-row:hover { background: var(--bg-hover); }
.guide-marker {
  flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1.5px solid var(--line-default);
}
.guide-marker .icon { width: 16px; height: 16px; }
.guide-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.guide-go { flex: 0 0 auto; color: var(--blue); margin-top: 1px; }
.guide-go .icon { width: 14px; height: 14px; }
.guide-task.done .guide-row { color: var(--text-disabled); }
.guide-task.done .guide-marker { border: 0; color: var(--success); }
.guide-task.done .guide-text { text-decoration: line-through; text-decoration-color: var(--line-default); }
.guide-task.next .guide-row { background: var(--bg-selected); color: var(--text-heading); font-weight: 600; }
.guide-task.next .guide-marker { border: 2px solid var(--blue); }
.guide-task.next button.guide-row:hover { background: #e3f0ff; }
.guide-done { display: flex; gap: var(--space-s); align-items: flex-start; font-size: 13px; color: var(--success); }
.guide-done .icon { margin-top: 2px; }
.guide-done p { margin: 0; color: var(--text-body); }

/* ==========================================================================
   Resource catalog (left column)
   ========================================================================== */

.resource-list { display: flex; flex-direction: column; }
.resource {
  display: grid; grid-template-columns: auto 1fr; column-gap: var(--space-s);
  align-items: center;
  padding: var(--space-s) var(--space-m);
  border: 1px solid var(--line-subtle); border-radius: var(--r-control);
  border-left: 3px solid var(--tint);
  background: var(--bg-container);
  margin-bottom: var(--space-s);
  cursor: grab; text-align: left;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.resource:hover { background: var(--bg-hover); border-color: var(--line-default); border-left-color: var(--tint); box-shadow: var(--shadow-container); }
.resource:active { cursor: grabbing; }
.resource .resource-icon { color: var(--tint); grid-row: span 2; }
.resource .resource-name { font-size: 13px; font-weight: 700; color: var(--text-heading); }
.resource .resource-desc { grid-column: 2; font-size: 11px; color: var(--text-secondary); }
.resource.placed {
  cursor: default; background: var(--bg-subtle); border-left-color: var(--line-default);
}
.resource.placed:hover { background: var(--bg-subtle); box-shadow: none; }
.resource.placed .resource-icon,
.resource.placed .resource-name { color: var(--text-disabled); }
.resource-flag {
  grid-column: 2; font-size: 11px; color: var(--success);
  display: inline-flex; align-items: center; gap: var(--space-xs); margin-top: var(--space-xxs);
}
.resource-flag .icon { width: 12px; height: 12px; }

.dispense-group { display: flex; flex-direction: column; gap: var(--space-s); }
.dispense-group + .section-label { margin-top: var(--space-l); }

/* Inline validated "Dispense AWS New Account" form. The blue left rule ties it
   back to the trigger above it, so the pair reads as one control. */
.dispense-form {
  display: flex; flex-direction: column; gap: var(--space-s);
  padding: var(--space-m);
  border: 1px solid var(--line-subtle); border-left: 3px solid var(--blue);
  border-radius: var(--r-control);
  background: var(--bg-subtle);
}
.dispense-form .field { margin-bottom: 0; }
.dispense-form .field select { font-size: 13px; }

/* ==========================================================================
   Board (architecture canvas)
   ========================================================================== */

/* Height is set from canvas.js to fit the topology (clamped) so the board does
   not leave a slab of empty grid when only a few nodes are placed. */
.board {
  position: relative; flex: 1 1 auto; min-height: var(--board-h, 440px); overflow: auto;
  border-radius: 0 0 var(--r-container) var(--r-container);
  background-color: var(--bg-container);
  background-image:
    linear-gradient(to right, var(--line-subtle) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line-subtle) 1px, transparent 1px);
  background-size: 40px 40px;
}
.board.drop-active { background-color: var(--bg-selected); box-shadow: inset 0 0 0 2px var(--blue); }

.board-empty {
  position: absolute; inset: 0; display: grid; place-content: center; justify-items: center;
  gap: var(--space-s); text-align: center; padding: var(--space-xl); pointer-events: none;
}
.board-empty .icon { width: 32px; height: 32px; color: var(--line-strong); }
.board-empty h3 { margin: 0; font-size: 16px; font-weight: 700; color: var(--text-heading); }
.board-empty p { margin: 0; font-size: 13px; color: var(--text-secondary); max-width: 46ch; }

.wire-layer { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.wire { fill: none; stroke-width: 1.5px; stroke-linecap: round; stroke-linejoin: round; }
.wire.pma-active { stroke: var(--blue); }
.wire.pma-pending { stroke: var(--line-strong); stroke-dasharray: 4 4; }
.wire.relationship { stroke: #7300e6; stroke-dasharray: 2 4; }
.wire.org-member { stroke: var(--line-default); }
.wire.bt-pending { stroke: var(--warning); stroke-dasharray: 6 4; }
.wire.bt-accepted { stroke: var(--success); stroke-dasharray: 6 4; }
.wire.bt-active { stroke: var(--success); stroke-width: 2.5px; }
/* Money moving along an Active transfer, in the bill's direction. */
.wire-flow {
  fill: none; stroke: #fff; stroke-width: 1.5px; stroke-linecap: round;
  stroke-dasharray: 2 14; opacity: 0.9;
  animation: wire-flow 1.2s linear infinite;
}
@keyframes wire-flow { to { stroke-dashoffset: -16; } }
/* A wire whose transfer just changed state draws itself in once. */
.wire.wire-new { stroke-dasharray: 1200; animation: wire-draw 900ms var(--ease) both; }
.wire.bt-pending.wire-new, .wire.bt-accepted.wire-new { animation: wire-glow 900ms var(--ease) both; stroke-dasharray: 6 4; }
@keyframes wire-draw { from { stroke-dashoffset: 1200; } to { stroke-dashoffset: 0; } }
@keyframes wire-glow { 0% { stroke-width: 5px; opacity: 0.4; } 100% { stroke-width: 1.5px; opacity: 1; } }
.wire.bt-inactive { stroke: var(--error); stroke-dasharray: 2 3; }

.wire-label {
  font-family: var(--font-body); font-size: 10px; font-weight: 600;
  fill: var(--text-secondary); paint-order: stroke;
  stroke: var(--bg-container); stroke-width: 4px; stroke-linejoin: round;
}

/* "No visibility" crossed-eye badge on the APN->PMA wire. */
.wire-badge.no-visibility { pointer-events: auto; }
.wire-badge-disc { fill: var(--bg-container); stroke: var(--warning); stroke-width: 1.5px; }
.wire-badge-eye { fill: none; stroke: var(--warning); stroke-width: 1.3px; }
.wire-badge-pupil { fill: var(--warning); }
.wire-badge-slash { stroke: var(--warning); stroke-width: 1.6px; stroke-linecap: round; }

/* Node cards */
.node {
  position: absolute; width: 176px; min-height: 84px;
  display: flex; flex-direction: column; gap: var(--space-xs);
  padding: var(--space-s) var(--space-m);
  background: var(--bg-container);
  border: 1px solid var(--line-default); border-top: 3px solid var(--tint);
  border-radius: var(--r-control);
  box-shadow: var(--shadow-container);
  cursor: grab; user-select: none; text-align: left;
  font: inherit; color: inherit;
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.node:hover { box-shadow: var(--shadow-raised); }
.node:active { cursor: grabbing; }
.node.dragging { box-shadow: var(--shadow-drag); z-index: 30; transition: none; }
.node.selected { border-color: var(--blue); box-shadow: 0 0 0 2px var(--blue); z-index: 20; }
/* The account the next guide step happens on: a soft blue halo that breathes,
   so the eye finds it without it competing with the selection ring. */
/* A node that just appeared, or just took on a new role / PMA status. */
.node.just-added { animation: node-in 360ms var(--ease) both; }
.node.just-changed { animation: node-pop 600ms var(--ease) both; }
@keyframes node-in { from { opacity: 0; transform: scale(0.92) translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes node-pop {
  0% { transform: scale(1); box-shadow: var(--shadow-container), 0 0 0 0 color-mix(in srgb, var(--tint) 60%, transparent); }
  35% { transform: scale(1.05); }
  100% { transform: scale(1); box-shadow: var(--shadow-container), 0 0 0 10px transparent; }
}
.node.shake { animation: node-shake 420ms var(--ease) both; border-color: var(--error); }
@keyframes node-shake {
  0%, 100% { transform: none; }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}
.node.next-target:not(.selected):not(.just-added):not(.just-changed) { animation: next-pulse 1.8s var(--ease) infinite; }
@keyframes next-pulse {
  0%, 100% { box-shadow: var(--shadow-container), 0 0 0 0 rgba(0, 108, 224, 0.45); }
  50% { box-shadow: var(--shadow-container), 0 0 0 6px rgba(0, 108, 224, 0); }
}
.node.error { border-color: var(--error); box-shadow: 0 0 0 2px var(--error-bg); }
/* Accounts owned by another party (scenario NPCs): muted, dashed, read-only. */
.node.npc { background: var(--bg-layout); border-style: dashed; border-top-style: solid; }
.node.active::after {
  content: ''; position: absolute; right: -5px; top: -5px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--success); box-shadow: 0 0 0 2px var(--bg-container);
}

.node-head { display: flex; align-items: center; gap: var(--space-s); min-width: 0; }
.node-head .icon { color: var(--tint); width: 15px; height: 15px; }
/* The plate is the card's anchor, so it is the one icon on screen that is fully
   tinted rather than washed — it lines up with the 3px tinted top border above
   it and the role label beside it. */
.node-plate {
  background: color-mix(in srgb, var(--tint) 14%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tint) 34%, #fff);
}
.node:hover .node-plate { background: color-mix(in srgb, var(--tint) 20%, #fff); }
.node-head-text { display: flex; flex-direction: column; min-width: 0; }
.node-name {
  font-size: 13px; font-weight: 700; color: var(--text-heading);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.node-role { font-size: 10px; font-weight: 700; color: var(--tint); text-transform: uppercase; letter-spacing: 0.4px; }
.node-id { font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); }
.node-badges { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin-top: auto; }

/* Badges */
.badge {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 600; line-height: 1.5;
  padding: 0 6px; border-radius: var(--r-badge);
  border: 1px solid var(--line-default); background: var(--bg-container); color: var(--text-secondary);
  white-space: nowrap;
}
.badge .icon { width: 10px; height: 10px; }
.badge.on { border-color: #b7f0bf; background: var(--success-bg); color: var(--success); }
.badge.pending { border-color: #f2e6b8; background: var(--warning-bg); color: var(--warning); }
.badge.off { color: var(--text-disabled); border-color: var(--line-subtle); }
.badge.info { border-color: #b8e7fb; background: var(--info-bg); color: var(--blue); font-family: var(--font-mono); }
.badge.accent { border-color: #e0c2a0; background: #fff8f0; color: var(--accent); }
.badge.owner { border-color: var(--line-default); background: var(--bg-subtle); color: var(--text-secondary); }

/* Board legend */
.legend {
  display: flex; flex-wrap: wrap; gap: var(--space-s) var(--space-l);
  padding: var(--space-s) var(--space-l);
  border-top: 1px solid var(--line-subtle);
  font-size: 11px; color: var(--text-secondary);
}
.legend-item { display: inline-flex; align-items: center; gap: var(--space-xs); }
.legend-swatch { width: 22px; height: 0; border-top-width: 2px; border-top-style: solid; }
.legend-swatch.pma-active { border-color: var(--blue); }
.legend-swatch.relationship { border-color: #7300e6; border-top-style: dashed; }
.legend-swatch.bt-pending { border-color: var(--warning); border-top-style: dashed; }
.legend-swatch.bt-accepted { border-color: var(--success); border-top-style: dashed; }
.legend-swatch.bt-active { border-color: var(--success); border-top-width: 3px; }
.legend-swatch.org-member { border-color: var(--line-default); }

/* ==========================================================================
   Inspector (right column)
   ========================================================================== */

/* Centred in the panel, since the panel is now full height. */
.insp-empty {
  display: grid; gap: var(--space-s); justify-items: center; align-content: center;
  text-align: center; min-height: 100%;
}
.insp-empty .icon { width: 28px; height: 28px; color: var(--line-strong); }
.insp-empty p { margin: 0; font-size: 13px; color: var(--text-secondary); }

.insp-identity {
  display: flex; gap: var(--space-s); align-items: flex-start;
  padding-bottom: var(--space-m); margin-bottom: var(--space-m);
  border-bottom: 1px solid var(--line-subtle);
}
.insp-identity .icon { width: 20px; height: 20px; color: var(--tint); margin-top: 2px; }
/* The official icon carries its own AWS colours and cannot be recoloured, so the
   role's --tint lives on the plate under it — the same lever the board node uses.
   The plate replaced an earlier 3px left rule here: one tinted shape reads more
   deliberately than a rule and a plate competing on the same row. The title stays
   at heading weight so the hierarchy doesn't soften for the roles tinted grey. */
.insp-identity .icon-plate {
  background: color-mix(in srgb, var(--tint) 14%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tint) 34%, #fff);
}
.insp-identity-title { font-size: 15px; font-weight: 700; color: var(--text-heading); }
.insp-identity-sub { font-family: var(--font-mono); font-size: 12px; color: var(--text-secondary); }

/* Collapsible sections (Account settings / Features / Actions). Each opens
   and closes from its heading; the meta note keeps a closed one informative. */
.insp-section { border-top: 1px solid var(--line-subtle); }
.insp-identity + .insp-section, .insp-identity + .callout + .insp-section { border-top: 0; }
.insp-section-head {
  display: flex; align-items: center; gap: var(--space-xs);
  padding: var(--space-m) 0; cursor: pointer; list-style: none; user-select: none;
}
.insp-section-head::-webkit-details-marker { display: none; }
.insp-section-head .section-label { margin: 0; }
.insp-section-head .chevron { display: inline-flex; color: var(--text-secondary); transition: transform var(--dur) var(--ease); }
.insp-section[open] > .insp-section-head .chevron { transform: rotate(90deg); }
.insp-section-head:hover .section-label { color: var(--blue); }
.insp-section-meta {
  margin-left: auto; font-size: 12px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 50%;
}
.insp-section-body { padding-bottom: var(--space-m); }

/* Form fields */
.field { display: block; margin-bottom: var(--space-m); }
.field > .field-label {
  display: block; font-size: 13px; font-weight: 700; color: var(--text-heading);
  margin-bottom: var(--space-xs);
}
.field > .field-hint { display: block; font-size: 12px; color: var(--text-secondary); margin-bottom: var(--space-xs); }
.field input, .field select {
  width: 100%; min-height: 32px; padding: 4px var(--space-s);
  font-family: var(--font-body); font-size: 14px; color: var(--text-body);
  background: var(--bg-container);
  border: 1px solid var(--line-default); border-radius: var(--r-control);
  transition: border-color var(--dur) var(--ease);
}
.field input[inputmode="numeric"] { font-family: var(--font-mono); }
.field input:hover, .field select:hover { border-color: var(--line-strong); }
.field input::placeholder { color: var(--text-disabled); }
.field input:read-only {
  background: var(--bg-subtle); color: var(--text-secondary); border-color: var(--line-subtle); cursor: default;
}
.field input[aria-invalid="true"] { border-color: var(--error); }
.field-error { font-size: 12px; color: var(--error); margin-top: var(--space-xs); }

/* Feature rows with a real toggle control */
.setting-list { display: flex; flex-direction: column; }
.setting {
  display: flex; gap: var(--space-m); align-items: flex-start; justify-content: space-between;
  padding: var(--space-m) 0; border-bottom: 1px solid var(--line-subtle);
}
.setting:last-child { border-bottom: 0; }
.setting-info { min-width: 0; }
/* IAM role names are long and unbreakable — let them wrap rather than overflow. */
/* The AWS service icon leads the setting name. Aligned to the first line rather
   than centred, because these labels wrap in the 360px panel. */
.setting-name {
  display: flex; align-items: flex-start; gap: var(--space-s);
  font-size: 13px; font-weight: 700; color: var(--text-heading);
}
.setting-name > span { min-width: 0; overflow-wrap: anywhere; padding-top: 2px; }
/* Nudged up so the 22px icon box optically centres on the first line of a label
   that may run to two or three lines in the 360px panel. */
.setting-name > .icon-plate,
.setting-name > .aws-icon { margin-top: -1px; }
.setting-help { font-size: 12px; color: var(--text-secondary); margin-top: var(--space-xxs); }
.setting-blocked {
  display: flex; gap: var(--space-xs); align-items: flex-start;
  font-size: 12px; color: var(--warning); margin-top: var(--space-xs);
}
.setting-blocked .icon { width: 13px; height: 13px; margin-top: 2px; }
.setting.blocked .setting-name { color: var(--text-secondary); }

/* Toggle switch (Cloudscape Toggle) */
.toggle { flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--space-s); cursor: pointer; }
.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle .track {
  position: relative; width: 34px; height: 20px; border-radius: 10px;
  background: var(--bg-container); border: 2px solid var(--line-strong);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.toggle .track::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 12px; height: 12px; border-radius: 50%; background: var(--line-strong);
  transition: transform var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.toggle input:checked + .track { background: var(--blue); border-color: var(--blue); }
.toggle input:checked + .track::after { transform: translateX(14px); background: #fff; }
.toggle input:focus-visible + .track { outline: 2px solid var(--blue); outline-offset: 2px; }
.toggle input:disabled + .track { border-color: var(--line-default); background: var(--bg-subtle); }
.toggle input:disabled + .track::after { background: var(--line-default); }
.toggle input:disabled:checked + .track { background: #9bc4ee; border-color: #9bc4ee; }
.toggle-state { font-size: 12px; color: var(--text-secondary); min-width: 22px; }
.toggle:has(input:disabled) { cursor: not-allowed; }

/* Config status callout */
.callout {
  display: flex; gap: var(--space-s); align-items: flex-start;
  font-size: 13px; padding: var(--space-s) var(--space-m); margin-bottom: var(--space-m);
  border: 1px solid var(--line-subtle); border-radius: var(--r-control);
}
.callout .icon { margin-top: 2px; }
/* The PMA verdict lists IAM role names, which are long and have no break
   opportunity, so without this they run past the panel's right edge. */
.callout > div { min-width: 0; overflow-wrap: anywhere; }
.callout.ok { background: var(--success-bg); border-color: #b7f0bf; color: var(--success); }
.callout.ok .icon { color: var(--success); }
.callout.warn { background: var(--warning-bg); border-color: #f2e6b8; color: var(--warning); }
.callout.warn .icon { color: var(--warning); }

/* Action cards (console forms) */
.action-card {
  border: 1px solid var(--line-subtle); border-radius: var(--r-control);
  padding: var(--space-m); margin-bottom: var(--space-m);
  background: var(--bg-container);
}
.action-card-head { display: flex; gap: var(--space-s); align-items: flex-start; justify-content: space-between; }
.action-card-title { font-size: 13px; font-weight: 700; color: var(--text-heading); overflow-wrap: anywhere; }
.action-card-help { font-size: 12px; color: var(--text-secondary); margin-top: var(--space-xxs); }
.action-card-form { margin-top: var(--space-m); }
.action-card-form .field:last-of-type { margin-bottom: var(--space-m); }
.action-card.disabled { background: var(--bg-subtle); }

/* Resource rows inside action cards (existing PMAs, relationships, transfers) */
.mini-table { margin: var(--space-m) 0 0; border-top: 1px solid var(--line-subtle); }
.mini-row {
  display: flex; align-items: center; gap: var(--space-s); justify-content: space-between;
  padding: var(--space-s) 0; border-bottom: 1px solid var(--line-subtle); font-size: 12px;
}
.mini-row-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mini-row-title { font-weight: 700; color: var(--text-heading); overflow-wrap: anywhere; }
.mini-row-sub { font-family: var(--font-mono); color: var(--text-secondary); font-size: 11px; }
.mini-row-note { color: var(--text-secondary); font-size: 11px; overflow-wrap: anywhere; }

/* Read-only facts about another party's account */
.kv-list { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-xs) var(--space-m); margin: 0; font-size: 12px; }
.kv-list dt { color: var(--text-secondary); }
.kv-list dd { margin: 0; color: var(--text-body); overflow-wrap: anywhere; }
.fact-list { margin: 0; padding-left: var(--space-l); font-size: 12px; color: var(--text-body); }
.fact-list li + li { margin-top: var(--space-xxs); }
.icon-btn {
  flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center;
  border: 1px solid transparent; border-radius: var(--r-badge);
  background: transparent; color: var(--text-secondary); cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.icon-btn:hover { background: var(--error-bg); color: var(--error); }

/* ==========================================================================
   Event log
   ========================================================================== */

/* Collapsible drawer under the columns: closed by default so it never pushes
   the board down; the summary keeps the event count and latest line visible. */
.log-section { max-width: var(--max-width); margin: var(--space-l) auto var(--space-xxl); padding: 0 var(--gutter); }
.log-summary {
  display: flex; align-items: baseline; gap: var(--space-s);
  padding: var(--space-s) var(--space-l);
  background: var(--bg-container); border-radius: var(--r-container);
  box-shadow: var(--shadow-container);
  cursor: pointer; list-style: none; user-select: none;
}
.log-summary::-webkit-details-marker { display: none; }
.log-summary:hover { background: var(--bg-hover); }
.log-summary .chevron { align-self: center; color: var(--text-secondary); transition: transform var(--dur) var(--ease); }
.log-section[open] .log-summary .chevron { transform: rotate(90deg); }
.log-section[open] .log-summary { margin-bottom: var(--space-m); }
.log-summary-title { font-size: 14px; font-weight: 700; color: var(--text-heading); white-space: nowrap; }
.log-summary .counter { font-size: 13px; color: var(--text-secondary); white-space: nowrap; }
.log-summary-latest {
  flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.log-summary-latest.has-error { color: var(--error); }
.log-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: var(--space-l); align-items: start; }
/* With no recorded errors the feed is the only child, so let it span the row. */
.log-grid:has(> :only-child) { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) { .log-grid { grid-template-columns: minmax(0, 1fr); } }

.log-feed { max-height: 220px; overflow-y: auto; }
.log-line {
  display: flex; gap: var(--space-s); align-items: baseline;
  padding: var(--space-xs) var(--space-l);
  font-size: 12.5px; color: var(--text-body);
  border-bottom: 1px solid var(--line-subtle);
}
.log-line:nth-child(odd) { background: #fcfcfd; }
.log-line .log-seq {
  flex: 0 0 auto; font-family: var(--font-mono); font-size: 11px; color: var(--text-disabled);
  font-variant-numeric: tabular-nums;
}
.log-line.log-error { color: var(--error); background: var(--error-bg); }
.log-line.log-npc { color: var(--blue); }
.log-empty { padding: var(--space-l); font-size: 13px; color: var(--text-secondary); margin: 0; }

.error-list { display: flex; flex-direction: column; }
.error-item {
  display: flex; gap: var(--space-s); align-items: flex-start;
  padding: var(--space-s) var(--space-l); border-bottom: 1px solid var(--line-subtle); font-size: 12.5px;
}
.error-item:last-child { border-bottom: 0; }
.error-item .icon { color: var(--error); width: 14px; height: 14px; margin-top: 2px; flex: 0 0 auto; }
.error-count {
  flex: 0 0 auto; font-family: var(--font-mono); font-weight: 600; color: var(--error);
  font-variant-numeric: tabular-nums;
}
.error-text { min-width: 0; }
.error-text b { color: var(--text-heading); }

/* ==========================================================================
   Motion preferences
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Scenario picker / briefing dialog */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center; padding: var(--space-l);
  background: rgba(15, 20, 26, 0.45);
}
.modal { width: min(760px, 100%); max-height: calc(100vh - 2 * var(--space-l)); overflow-y: auto; box-shadow: var(--shadow-raised); }
.modal .container-header { display: flex; align-items: center; justify-content: space-between; }
.scenario-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-m); margin-top: var(--space-m); }
.scenario-card {
  display: flex; flex-direction: column; gap: var(--space-s);
  padding: var(--space-m); border: 1px solid var(--line-default); border-radius: var(--r-control);
  border-top: 3px solid var(--tint, var(--line-strong));
}
.scenario-card .icon-plate {
  background: color-mix(in srgb, var(--tint) 14%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tint) 34%, #fff);
}
.scenario-card-titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.scenario-meta { display: flex; align-items: center; gap: var(--space-xs); font-size: 12px; color: var(--text-secondary); }
.scenario-summary { margin: 0; font-size: 13px; color: var(--text-body); }
.scenario-goal {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--space-s); border-radius: var(--r-badge); background: var(--bg-subtle);
  font-size: 12px; color: var(--text-heading); font-weight: 600;
}
.scenario-goal-label { font-size: 10px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-secondary); }
.scenario-card.current { border-color: var(--blue); box-shadow: 0 0 0 1px var(--blue); }
.scenario-card .btn { align-self: flex-start; margin-top: auto; }
.scenario-card-head { display: flex; align-items: center; gap: var(--space-s); }
.scenario-title { font-size: 15px; font-weight: 700; color: var(--text-heading); }

/* Scenario results */
.result-hero { display: flex; gap: var(--space-m); align-items: center; margin-bottom: var(--space-l); }
.result-hero > .icon { width: 36px; height: 36px; color: var(--success); }
.result-goal { margin: 0; font-size: 16px; font-weight: 700; color: var(--text-heading); }
.result-stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-m);
  margin: 0 0 var(--space-l);
}
.result-stats > div { padding: var(--space-s) var(--space-m); border: 1px solid var(--line-subtle); border-radius: var(--r-control); }
.result-stats dt { font-size: 10px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-secondary); }
.result-stats dd { margin: 0; font-size: 22px; font-weight: 700; color: var(--text-heading); font-variant-numeric: tabular-nums; }
.result-stats dd.tone-score { color: var(--blue); }
.result-stats dd.tone-error { color: var(--error); }
.result-stats dd.tone-warn { color: var(--warning); }
.result-errors { list-style: none; margin: 0 0 var(--space-m); padding: 0; display: flex; flex-direction: column; gap: var(--space-s); font-size: 13px; }
.result-errors li { display: flex; gap: var(--space-s); align-items: flex-start; }
.result-errors b { color: var(--text-heading); }
.result-actions { display: flex; flex-wrap: wrap; gap: var(--space-s); margin-top: var(--space-l); }
@media (max-width: 600px) { .result-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ==========================================================================
   Challenge mode
   ========================================================================== */

.stat-tile.tone-money { --tone: var(--success); }
.stat-tile.tone-money .stat-value { color: var(--success); }
.target-bar {
  display: block; width: 100%; min-width: 96px; height: 4px; margin-top: 3px;
  border-radius: 2px; background: var(--line-subtle); overflow: hidden;
}
.target-bar > span { display: block; height: 100%; background: var(--success); transition: width 600ms var(--ease); }
.stat-tile.urgent { --tone: var(--error); }
.stat-tile.urgent .stat-note { color: var(--error); font-weight: 700; }

.mission-goal { margin: 0 0 var(--space-s); font-size: 13px; color: var(--text-body); }
.mission-progress { height: 8px; border-radius: 4px; background: var(--line-subtle); overflow: hidden; margin-bottom: var(--space-xs); }
.mission-progress > span { display: block; height: 100%; background: var(--success); transition: width 600ms var(--ease); }
.mission-tip { margin: var(--space-m) 0; font-size: 12px; color: var(--text-secondary); line-height: 1.45; }
.mission-hint { border-top: 1px solid var(--line-subtle); padding-top: var(--space-m); }
.mission-hint-text {
  display: flex; gap: var(--space-s); align-items: flex-start; margin: 0 0 var(--space-xs);
  padding: var(--space-s); border-radius: var(--r-badge); background: var(--bg-selected);
  font-size: 12.5px; font-weight: 600; color: var(--text-heading);
}
.mission-hint-text .icon { color: var(--blue); margin-top: 1px; }

.badge.urgent { border-color: #f5c2c2; background: var(--error-bg); color: var(--error); }

/* A prospect's remaining patience, pinned to the card's top-right corner so it
   never pushes the card taller than its lattice cell. */
.node-timer {
  position: absolute; top: 6px; right: 6px;
  display: inline-flex; align-items: center; gap: 2px;
  padding: 0 5px; border-radius: 9px;
  font-size: 10px; font-weight: 700; line-height: 16px;
  background: var(--warning-bg); color: var(--warning); border: 1px solid #f2e6b8;
}
.node-timer .icon { width: 10px; height: 10px; }
.node-timer.urgent { background: var(--error-bg); color: var(--error); border-color: #f5c2c2; animation: timer-pulse 1.2s var(--ease) infinite; }
@keyframes timer-pulse { 50% { transform: scale(1.12); } }

.alert-warning { background: var(--warning-bg); border-color: #f2e6b8; align-items: center; }
.alert-warning .icon { color: var(--warning); }

.scenario-actions { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin-top: auto; }
.scenario-card .scenario-actions .btn { align-self: auto; margin-top: 0; }
.scenario-challenge {
  display: flex; gap: var(--space-xs); align-items: center; margin: 0;
  font-size: 12px; font-weight: 600; color: var(--success);
}
.scenario-challenge .icon { width: 14px; height: 14px; }
.briefing-challenge { margin-top: var(--space-l); color: var(--success); }

.result-hero.lost > .icon { color: var(--warning); }
.result-stars { margin-left: auto; font-size: 30px; letter-spacing: 2px; white-space: nowrap; }
.result-stars .star { color: var(--line-default); }
.result-stars .star.on { color: #e8a200; animation: star-pop 500ms var(--ease) both; }
.result-stars .star.on:nth-child(2) { animation-delay: 150ms; }
.result-stars .star.on:nth-child(3) { animation-delay: 300ms; }
@keyframes star-pop { 0% { transform: scale(0); } 70% { transform: scale(1.3); } 100% { transform: scale(1); } }
.result-star-rules { margin: calc(-1 * var(--space-s)) 0 var(--space-l); }

.node:has(.node-timer) .node-head { padding-right: 50px; }

/* Feedback dialog */
.feedback-form { margin-top: var(--space-m); }
.feedback-form .field textarea {
  width: 100%; padding: 6px var(--space-s); resize: vertical;
  font-family: var(--font-body); font-size: 14px; color: var(--text-body);
  background: var(--bg-container);
  border: 1px solid var(--line-default); border-radius: var(--r-control);
}
.feedback-form .field textarea:hover { border-color: var(--line-strong); }
.segmented-field { border: 0; padding: 0; min-width: 0; }
.segmented-field > legend { padding: 0; margin-bottom: var(--space-xs); }
.segmented { display: flex; flex-wrap: wrap; gap: var(--space-xs); }
.segment { position: relative; cursor: pointer; }
.segment input { position: absolute; opacity: 0; width: 0; height: 0; }
.segment span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; min-height: 32px; padding: 4px var(--space-m);
  font-size: 14px; color: var(--text-body);
  border: 1px solid var(--line-default); border-radius: var(--r-control);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.segment:hover span { border-color: var(--line-strong); }
.segment input:checked + span { background: var(--bg-selected); border-color: var(--blue); color: var(--blue); font-weight: 700; }
.segment input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 2px; }
.feedback-privacy { margin: 0 0 var(--space-m); font-size: 12px; color: var(--text-secondary); }
.form-actions { display: flex; justify-content: flex-end; gap: var(--space-s); }
