/* ═══════════════════════════════════════════════════════════════════════════
   geds-dashboard.css — the dashboard-geds.neuralciberguard.org preview.
   ---------------------------------------------------------------------------
   A working miniature of the real control plane, sitting on the landing page.
   It is a DEMO and says so: no login, no network, no customer data. Everything
   it shows is generated in the browser from a fixed script.

   WHY A DEMO AND NOT A SCREENSHOT
   The whole claim of this product is "four surfaces, one incident". A static
   image cannot show correlation happening — alerts arriving separately and
   then collapsing into a single incident is the product, and it only reads
   when you watch it occur. A screenshot would also go stale the first time the
   real dashboard's chrome changes.

   COLOUR
   Consumes the neural.css tokens, so it follows the theme automatically. The
   mineral accents come from geds-theme.css. Severity colours are the only
   hard-coded values here and they are deliberate: they must be identical
   across every Guardian surface, so they belong to the product, not the theme.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- interactive demo shell (controls + attacker rail + the window) ------
   .gdemo is the mount root. It carries the product severity scale as custom
   properties so the attacker rail can use the same colours as the dashboard
   card without redefining them. The card itself is .gdash, a child. */
.gdemo {
  --gd-bg:      var(--cream-2, #F3F1EA);
  --gd-panel:   var(--cream, #FAF9F6);
  --gd-line:    var(--crimson-line, rgba(145,73,85,.22));
  --gd-ink:     var(--ink, #1C1917);
  --gd-ink-2:   var(--ink-2, #44403C);
  --gd-ink-3:   var(--ink-3, #78716C);
  --gd-accent:  var(--crimson, #914955);

  --sev-low:      #2F6B4F;
  --sev-medium:   #B4653A;
  --sev-high:     #A8442F;
  --sev-critical: #8C1F2F;

  display: grid;
  gap: 14px;
  font-family: var(--sans, Inter, system-ui, sans-serif);
}

/* ---- controls ------------------------------------------------------------ */

.gdemo__ctl {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.gdemo__play {
  display: inline-flex;
  align-items: center;
  gap: .6ch;
  padding: .72em 1.15em;
  border: 0;
  border-radius: 10px;
  background: var(--gd-accent);
  color: #fff;
  font: 600 13.5px/1 var(--sans, Inter, sans-serif);
  cursor: pointer;
  transition: transform .18s ease, filter .18s ease;
  /* A quiet breathing pulse invites the first press; it stops the instant the
     button is disabled (i.e. during a run). Removed under reduced motion. */
  animation: gdemo-invite 2.6s ease-in-out infinite;
}
.gdemo__play:hover:not(:disabled) { transform: translateY(-1px); filter: brightness(1.06); }
.gdemo__play:focus-visible { outline: 2px solid var(--gd-accent); outline-offset: 3px; }
.gdemo__play:disabled { opacity: .5; cursor: default; animation: none; }
@keyframes gdemo-invite {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gd-accent) 40%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in srgb, var(--gd-accent) 0%, transparent); }
}
.gdemo__reset {
  padding: .72em 1.1em;
  border: 1px solid var(--gd-line);
  border-radius: 10px;
  background: var(--gd-panel);
  color: var(--gd-ink-2);
  font: 500 13px/1 var(--sans, Inter, sans-serif);
  cursor: pointer;
}
.gdemo__reset:disabled { opacity: .5; cursor: default; }
.gdemo__reset:focus-visible { outline: 2px solid var(--gd-accent); outline-offset: 3px; }
.gdemo__status {
  font: 500 11px/1.3 var(--mono, ui-monospace, monospace);
  letter-spacing: .04em;
  color: var(--gd-ink-3);
}

/* ---- attacker kill chain ------------------------------------------------- */

.gdemo__attack {
  padding: 14px 16px;
  border: 1px solid var(--gd-line);
  border-radius: 14px;
  background: var(--gd-panel);
}
.gkill {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}
@media (min-width: 760px) {
  /* Five beats read as a horizontal chain on wide screens. */
  .gkill { grid-template-columns: repeat(5, 1fr); gap: 10px; }
}
.gkill__step {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: 'n txt' 'catch catch';
  align-items: start;
  gap: 4px 10px;
  padding: 10px 11px;
  border: 1px solid var(--gd-line);
  border-radius: 11px;
  background: var(--gd-bg);
  opacity: .5;
  transition: opacity .4s ease, border-color .4s ease, transform .4s ease;
}
.gkill__step.is-active {
  opacity: 1;
  border-color: var(--sev-high);
  transform: translateY(-2px);
}
.gkill__step.is-done { opacity: 1; }
.gkill__n {
  grid-area: n;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--gd-line);
  background: var(--gd-panel);
  font: 600 11px/1 var(--mono, ui-monospace, monospace);
  color: var(--gd-ink-3);
}
.gkill__step.is-done .gkill__n {
  background: var(--sev-low);
  border-color: var(--sev-low);
  color: #fff;
  font-size: 0;                 /* hide the number, show a tick via ::before */
}
.gkill__step.is-done .gkill__n::before { content: '✓'; font-size: 12px; }
.gkill__txt { grid-area: txt; min-width: 0; }
.gkill__txt b { display: block; font-size: 12px; line-height: 1.3; color: var(--gd-ink); }
.gkill__txt small { display: block; margin-top: 3px; font-size: 10px; line-height: 1.35; color: var(--gd-ink-3); }
.gkill__catch {
  grid-area: catch;
  justify-self: start;
  margin-top: 2px;
  padding: .2em .6em;
  border-radius: 999px;
  font: 600 9px/1.4 var(--mono, ui-monospace, monospace);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #fff;
  opacity: 0;
  transition: opacity .3s ease;
}
.gkill__step.is-active .gkill__catch,
.gkill__step.is-done .gkill__catch { opacity: 1; }
.gkill__catch[data-surface='sentry']  { background: var(--sev-high); }
.gkill__catch[data-surface='desktop'] { background: var(--gd-accent); }

.gdash {
  --gd-bg:      var(--cream-2, #F3F1EA);
  --gd-panel:   var(--cream, #FAF9F6);
  --gd-line:    var(--crimson-line, rgba(145,73,85,.22));
  --gd-ink:     var(--ink, #1C1917);
  --gd-ink-2:   var(--ink-2, #44403C);
  --gd-ink-3:   var(--ink-3, #78716C);
  --gd-accent:  var(--crimson, #914955);

  /* Product severity scale — identical on Desktop, Mobile, Sentry and here. */
  --sev-low:      #2F6B4F;
  --sev-medium:   #B4653A;
  --sev-high:     #A8442F;
  --sev-critical: #8C1F2F;

  position: relative;
  border: 1px solid var(--gd-line);
  border-radius: 16px;
  background: var(--gd-bg);
  overflow: hidden;
  box-shadow: var(--shadow, 0 10px 30px rgba(28,25,23,.06));
  font-family: var(--sans, Inter, system-ui, sans-serif);
}

/* ---- window chrome ------------------------------------------------------- */

.gdash__bar {
  display: flex;
  align-items: center;
  gap: 1ch;
  padding: 10px 14px;
  border-bottom: 1px solid var(--gd-line);
  background: var(--gd-panel);
}
.gdash__dots { display: flex; gap: 6px; }
.gdash__dots i {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--gd-line);
}
.gdash__url {
  flex: 1;
  /* min-width:0 matters: a flex item's min size defaults to its content, so on
     very narrow viewports (~322px) the full hostname refused to shrink and
     pushed the DEMO badge past the right edge — the last horizontal-scroll
     source §4.4 found after the .grid fix. Ellipsis instead of overflow. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  font: 500 11.5px/1 var(--mono, ui-monospace, monospace);
  color: var(--gd-ink-3);
  letter-spacing: .03em;
}
.gdash__live { flex: none; }
.gdash__live {
  display: inline-flex; align-items: center; gap: .5ch;
  font: 500 10.5px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--sev-low);
}
.gdash__live::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
  animation: gd-pulse 2.4s ease-in-out infinite;
}
@keyframes gd-pulse { 0%,100% { opacity: 1 } 50% { opacity: .25 } }

/* ---- layout -------------------------------------------------------------- */

.gdash__body {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--gd-line);
}
@media (min-width: 880px) {
  .gdash__body { grid-template-columns: 168px 1fr 300px; }
}

.gdash__col { background: var(--gd-bg); padding: 16px; min-width: 0; }
.gdash__col--nav { display: none; }
@media (min-width: 880px) { .gdash__col--nav { display: block; } }

.gdash__navlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.gdash__navlist li {
  padding: .55em .7em;
  border-radius: 8px;
  font-size: 12.5px;
  color: var(--gd-ink-2);
}
.gdash__navlist li[aria-current='true'] {
  background: var(--crimson-soft, rgba(145,73,85,.08));
  color: var(--gd-accent);
  font-weight: 600;
}

.gdash__h {
  margin: 0 0 10px;
  font: 500 10.5px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--gd-ink-3);
}

/* ---- fleet tiles --------------------------------------------------------- */

.gdash__fleet {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-bottom: 18px;
}
@media (min-width: 560px) { .gdash__fleet { grid-template-columns: repeat(4, 1fr); } }

.gdtile {
  padding: 10px;
  border: 1px solid var(--gd-line);
  border-radius: 10px;
  background: var(--gd-panel);
  transition: border-color .4s ease, transform .4s ease;
}
.gdtile.is-hot {
  border-color: var(--sev-high);
  transform: translateY(-2px);
}
.gdtile b {
  display: block;
  font: 500 10px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--gd-ink-3);
  margin-bottom: 6px;
}
.gdtile span {
  font: 400 20px/1 var(--serif, Fraunces, Georgia, serif);
  color: var(--gd-ink);
}
.gdtile em {
  display: block; margin-top: 4px; font-style: normal;
  font-size: 10.5px; color: var(--gd-ink-3);
}

/* ---- alert feed ---------------------------------------------------------- */

.gdash__feed { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }

.gdrow {
  display: grid;
  grid-template-columns: 4px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border: 1px solid var(--gd-line);
  border-radius: 9px;
  background: var(--gd-panel);
  /* Rows are inserted by JS; this is their entrance. */
  animation: gd-in .45s cubic-bezier(.22,.61,.36,1) both;
}
@keyframes gd-in { from { opacity: 0; transform: translateY(-6px) } to { opacity: 1; transform: none } }

.gdrow i { align-self: stretch; border-radius: 2px; background: var(--sev-low); }
.gdrow[data-sev='medium']   i { background: var(--sev-medium); }
.gdrow[data-sev='high']     i { background: var(--sev-high); }
.gdrow[data-sev='critical'] i { background: var(--sev-critical); }

.gdrow p { margin: 0; font-size: 12.5px; color: var(--gd-ink); line-height: 1.35; }
.gdrow small { display: block; margin-top: 2px; font-size: 10.5px; color: var(--gd-ink-3); }
.gdrow time {
  font: 500 10.5px/1 var(--mono, ui-monospace, monospace);
  color: var(--gd-ink-3);
  white-space: nowrap;
}
.gdrow.is-linked {
  border-color: color-mix(in srgb, var(--gd-accent) 45%, var(--gd-line));
  background: var(--crimson-soft, rgba(145,73,85,.06));
}

/* ---- incident panel ------------------------------------------------------ */

.gdinc {
  border: 1px solid var(--gd-line);
  border-radius: 12px;
  background: var(--gd-panel);
  padding: 14px;
  opacity: .45;
  transition: opacity .6s ease, border-color .6s ease;
}
.gdinc.is-open {
  opacity: 1;
  border-color: color-mix(in srgb, var(--gd-accent) 50%, var(--gd-line));
}
.gdinc__sev {
  display: inline-block;
  padding: .3em .7em;
  border-radius: 999px;
  font: 600 10px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .12em; text-transform: uppercase;
  color: #fff; background: var(--sev-critical);
}
.gdinc h4 {
  margin: 10px 0 6px;
  font: 400 17px/1.25 var(--serif, Fraunces, Georgia, serif);
  color: var(--gd-ink);
}
.gdinc__ai {
  margin: 10px 0 0;
  font-size: 12.5px; line-height: 1.55; color: var(--gd-ink-2);
  min-height: 5.2em;   /* reserved, so the panel does not jump as text types in */
}
.gdinc__ai::after {
  content: '▌'; color: var(--gd-accent);
  animation: gd-caret 1s steps(1) infinite;
}
.gdinc.is-done .gdinc__ai::after { content: none; }
@keyframes gd-caret { 0%,50% { opacity: 1 } 51%,100% { opacity: 0 } }

.gdinc__meta {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--gd-line);
  display: grid; gap: 4px;
  font: 500 10.5px/1.5 var(--mono, ui-monospace, monospace);
  color: var(--gd-ink-3);
}

/* ---- footnote ------------------------------------------------------------ */

.gdash__note {
  padding: 9px 14px;
  border-top: 1px solid var(--gd-line);
  background: var(--gd-panel);
  font-size: 11.5px;
  color: var(--gd-ink-3);
}

/* ---- reduced motion ------------------------------------------------------ */
/* No entrance, no caret, no pulse. geds-dashboard.js also renders the FINAL
   state immediately in this mode rather than playing the sequence, so the
   correlated incident is visible without waiting for an animation that will
   never run. */
@media (prefers-reduced-motion: reduce) {
  .gdrow { animation: none; }
  .gdinc__ai::after { content: none; }
  .gdash__live::before { animation: none; }
  .gdtile { transition: none; }
  .gdinc { transition: none; }
  .gdemo__play { animation: none; transition: none; }
  .gkill__step { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Guardian Mobile + Senior — the phone demo.
   ---------------------------------------------------------------------------
   Sits where the static "incident assistant" illustration used to. That
   picture showed the Dashboard, and the Dashboard now has a working preview
   further up this page — the illustration was the page describing the same
   product twice, once frozen.

   VERDICT IS NEVER COLOUR ALONE. Every state carries an icon, a word and a
   sentence. A red panel means nothing to a reader who cannot see red, and this
   is precisely the audience Senior mode exists for.
   ═══════════════════════════════════════════════════════════════════════════ */

.gphone-wrap {
  --v-safe:    #2F6B4F;
  --v-scam:    #A8442F;
  --v-suspect: #B4653A;
  display: grid;
  gap: 14px;
  font-family: var(--sans, Inter, system-ui, sans-serif);
}

/* ---- scenario strip ------------------------------------------------------ */

.gphone__tabs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
}
.gphone__tab {
  display: grid;
  gap: 4px;
  padding: 10px 11px;
  text-align: left;
  border: 1px solid var(--crimson-line, rgba(145,73,85,.22));
  border-radius: 11px;
  background: var(--cream, #FAF9F6);
  color: var(--ink, #1C1917);
  cursor: pointer;
  transition: border-color .25s ease, transform .25s ease;
}
.gphone__tab:hover { transform: translateY(-2px); }
.gphone__tab:focus-visible { outline: 2px solid var(--crimson, #914955); outline-offset: 2px; }
.gphone__tab[aria-selected='true'] {
  background: var(--charcoal, #1C1917);
  color: var(--cream, #FAF9F6);
  border-color: var(--charcoal, #1C1917);
}
.gphone__tab b { font-size: 12.5px; font-weight: 600; }
.gphone__tab em {
  font-style: normal; font-size: 10.5px; line-height: 1.35;
  color: var(--ink-3, #78716C);
}
.gphone__tab[aria-selected='true'] em { color: rgba(255,255,255,.72); }

.gphone__tab-badge {
  justify-self: start;
  padding: .22em .6em;
  border-radius: 999px;
  font: 700 9px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .1em;
  color: #fff;
}
.gphone__tab-badge[data-v='safe']    { background: var(--v-safe); }
.gphone__tab-badge[data-v='scam']    { background: var(--v-scam); }
.gphone__tab-badge[data-v='suspect'] { background: var(--v-suspect); }

/* ---- the phone ----------------------------------------------------------- */

.gphone {
  justify-self: center;
  width: min(100%, 340px);
  border: 1px solid var(--crimson-line, rgba(145,73,85,.22));
  border-radius: 26px;
  background: var(--cream-2, #F3F1EA);
  padding: 10px;
  box-shadow: var(--shadow, 0 12px 34px rgba(28,25,23,.10));
}
.gphone__note {
  text-align: center;
  padding: 2px 0 8px;
  font: 500 9.5px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--ink-3, #78716C);
}
.gphone__screen {
  border-radius: 18px;
  overflow: hidden;
  background: var(--cream, #FAF9F6);
  border: 1px solid var(--crimson-line, rgba(145,73,85,.18));
}
.gphone__chrome {
  display: flex; align-items: center; gap: .6ch;
  padding: 8px 10px;
  background: var(--cream-3, #ECE9E0);
  border-bottom: 1px solid var(--crimson-line, rgba(145,73,85,.16));
}
.gphone__url {
  font: 500 10px/1.3 var(--mono, ui-monospace, monospace);
  color: var(--ink-2, #44403C);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gphone__app { padding: 12px; }
.gphone__appbar {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1ch; margin-bottom: 12px;
}
.gphone__appbar b { font-size: 13px; }
.gphone__state { font-size: 10.5px; color: var(--ink-3, #78716C); }

/* ---- verdict ------------------------------------------------------------- */

.gphone__verdict {
  text-align: center;
  padding: 16px 12px;
  border-radius: 12px;
  border: 1px solid;
}
.gphone__verdict[data-verdict='safe']    { color: var(--v-safe);    border-color: color-mix(in srgb, var(--v-safe) 34%, transparent);    background: color-mix(in srgb, var(--v-safe) 8%, transparent); }
.gphone__verdict[data-verdict='scam']    { color: var(--v-scam);    border-color: color-mix(in srgb, var(--v-scam) 34%, transparent);    background: color-mix(in srgb, var(--v-scam) 8%, transparent); }
.gphone__verdict[data-verdict='suspect'] { color: var(--v-suspect); border-color: color-mix(in srgb, var(--v-suspect) 34%, transparent); background: color-mix(in srgb, var(--v-suspect) 8%, transparent); }

.gphone__title {
  margin: 8px 0 4px;
  font: 400 18px/1.2 var(--serif, Fraunces, Georgia, serif);
  color: inherit;
}
.gphone__line {
  margin: 0; font-size: 12px; line-height: 1.5;
  color: var(--ink-2, #44403C);
}

/* ---- signals ------------------------------------------------------------- */

.gphone__sigh {
  margin: 14px 0 8px;
  font: 500 9.5px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-3, #78716C);
}
.gphone__signals { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.gphone__signals li {
  display: grid; gap: 2px;
  padding-left: 16px;
  position: relative;
  font-size: 11px; line-height: 1.45;
}
.gphone__signals li::before {
  content: '';
  position: absolute; left: 0; top: .45em;
  width: 7px; height: 7px; border-radius: 2px;
  background: var(--crimson, #914955);
}
.gphone__signals b { font-size: 11.5px; color: var(--ink, #1C1917); }
.gphone__signals span { color: var(--ink-3, #78716C); }

/* ---- family ------------------------------------------------------------- */

.gphone__family {
  width: 100%;
  margin-top: 14px;
  padding: .8em 1em;
  border: 0;
  border-radius: 10px;
  background: var(--crimson, #914955);
  color: #fff;
  font: 600 12.5px/1 var(--sans, Inter, sans-serif);
  cursor: pointer;
}
.gphone__family:disabled { opacity: .55; cursor: default; }
.gphone__family:focus-visible { outline: 2px solid var(--crimson, #914955); outline-offset: 3px; }
.gphone__fam-note {
  margin: 8px 0 0; text-align: center;
  font-size: 10.5px; line-height: 1.45;
  color: var(--ink-3, #78716C);
}

@media (prefers-reduced-motion: reduce) {
  .gphone__tab { transition: none; }
  .gphone__tab:hover { transform: none; }
}

/* ---- SMS view ------------------------------------------------------------ */
/* A text message has no address bar. Showing browser chrome around an SMS is
   the fastest way to make a demo look like a mock-up of something nobody uses,
   so the renderer swaps the whole header for a sender line and a bubble. */
.gphone__sms {
  padding: 12px 12px 4px;
  border-bottom: 1px solid var(--crimson-line, rgba(145,73,85,.16));
  background: var(--cream-3, #ECE9E0);
}
.gphone__sms-from {
  display: block;
  font: 600 10.5px/1 var(--mono, ui-monospace, monospace);
  letter-spacing: .06em;
  color: var(--ink-3, #78716C);
  margin-bottom: 7px;
}
.gphone__sms-body {
  margin: 0 0 10px;
  padding: 10px 12px;
  border-radius: 14px 14px 14px 4px;
  background: var(--cream, #FAF9F6);
  border: 1px solid var(--crimson-line, rgba(145,73,85,.18));
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink, #1C1917);
  /* Long scam URLs must wrap rather than force the phone wider. */
  overflow-wrap: anywhere;
}
