/* ==========================================================================
   THREE-PANEL PROOF OF CONCEPT — three.css

   Loads AFTER style.css and overrides its layout only. Everything that makes
   a bubble look like a bubble still comes from style.css.

   Wide screens:  graph | conversation | call to action
   Narrow:        just the conversation, then the card underneath — the same
                  thing the real page does, because three columns on a phone
                  is three cramped columns.
   ========================================================================== */

:root {
  --panel-gap:  clamp(16px, 3vw, 40px);
  --node:       #2b6cf6;      /* the dots */
  --node-soft:  #8ba9e8;      /* the ones further from the cursor */
  --edge:       #b3b2a8;      /* the lines between them */
  --edge-label: #4a4e55;      /* the words next to the dots */
  --online:     #26a86c;      /* the status dot. the one non-blue on the page,
                                 and at 7px it reads as a signal, not a colour */

  /* --- the three panels ---------------------------------------------------
     GRADIENTS, WITH A RULE: one hue, and a range of about five percent. What
     makes a page look machine-generated is a gradient that travels between two
     different colours — the purple-to-blue diagonal. A gradient inside a
     single colour just reads as light falling on a surface, which is the
     whole effect worth having. */
  --panel-bg:     linear-gradient(180deg, rgba(255,255,255,0.76), rgba(255,255,255,0.50));
  --panel-edge:   rgba(17, 18, 20, 0.07);
  --panel-shadow: 0 10px 30px rgba(17, 18, 20, 0.05);
  --panel-radius: 24px;

  /* The chat header's height. The graph's title is pushed down by the same
     amount, which is what puts it on the same line as the 10:10 stamp. One
     value, so they cannot drift apart. */
  --header-h: 20px;

  /* How far below the header the graph's title sits. --s4 puts it on the
     10:10 stamp; more drops it toward the first bubble. */
  --title-drop: var(--s7);
}

/* style.css puts the page in a sticky two-screen scroller. None of that
   applies here, so the body is an ordinary page again. */
/* The page itself, barely. Top to bottom, inside the one off-white — enough
   that the panels have something to sit on, not enough to notice. */
body.three {
  overflow: auto;
  background: linear-gradient(180deg, #faf9f5 0%, #f2f1ea 100%);
  background-attachment: fixed;
}

/* Wide: no extra scroll, the three columns are the whole page. */
body.three .scroller { height: auto; }
body.three .scroll-hint { display: none; }

.grid {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  /* Three equal columns. They used to be 1fr | 420px | 1fr, which made the
     graph and the card wider than the conversation between them. */
  grid-template-columns: repeat(3, minmax(0, var(--column)));
  justify-content: center;
  gap: var(--panel-gap);
  align-items: stretch;         /* all three the same height */
  padding: var(--s5) var(--panel-gap);
  margin: 0 auto;
}

/* Each area gets its own surface, so the boundary between them is a thing you
   can see rather than a gap you infer. */
.panel {
  min-width: 0;                 /* lets grid children shrink; without it the
                                   conversation forces the page wider */
  display: flex;
  flex-direction: column;
  padding: var(--s5);
  border-radius: var(--panel-radius);
  background: var(--panel-bg);
  border: 1px solid var(--panel-edge);
  box-shadow: var(--panel-shadow);
}

/* The chat header. Sits above the conversation because that is where a
   messaging app puts who you are talking to — and the quiet claim it makes is
   the real one: there is no app to open, so it is always on. */
.status {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--size-small);
  color: var(--ink-soft);
  height: var(--header-h);
}

.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--online);
  /* A soft ring rather than a glow — the halo is what stops a small dot on a
     pale background reading as a speck of dust. */
  box-shadow: 0 0 0 3px rgba(38, 168, 108, 0.15);
}

/* --- the graph's title ---------------------------------------------------
   A statement, not a heading. Big, heavy, tight, and broken across three
   lines on purpose — a short line stack reads as a claim, where the same
   words set on one line read as a caption for the picture below.

   Tight leading and negative tracking are what make large type look set
   rather than just enlarged. Both matter more as the size goes up. */
.graph-title {
  text-align: center;
  font-size: clamp(26px, 3.2vw, 34px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
  margin-top: calc(var(--header-h) + var(--title-drop));
  margin-bottom: var(--s3);
}

/* --- the graph -----------------------------------------------------------
   No surface of its own. The panel is already a card, and a second circular
   one inside it was a border around a shape the nodes were drawing anyway.

   The layout is still circular — that lives in RINGS in three.js — this just
   stops framing it. */
.graph {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  /* Sits under the heading rather than centring in the leftover space. The
     auto margins it had were splitting the gap above and below it, which put
     a large hole between the heading and the graph and left the panel bottom
     looking padded for no reason. */
  margin-top: var(--s4);
}
.graph svg { width: 100%; height: 100%; display: block; overflow: visible; }

.graph .hub-label {
  font-size: 13px;
  font-weight: 600;
  fill: var(--ink);
}

.graph text {
  font-family: var(--font);
  font-size: 11px;
  fill: var(--edge-label);
  paint-order: stroke;         /* draws the halo behind the glyphs, so a label
                                  stays readable when a line passes under it */
  stroke: var(--ground);
  stroke-width: 3px;
}

/* --- the conversation ---------------------------------------------------- */
/* style.css has .thread filling a sticky stage. Here it is a column that
   starts right under the header — top-aligned rather than centred, so the
   10:10 stamp lands at a predictable height for the graph's title to match. */
.panel-thread .thread {
  height: auto;
  flex: 1;
  justify-content: flex-start;
  padding-bottom: 0;
  overflow: visible;
}

/* --- the card ------------------------------------------------------------
   The panel is translucent and quiet; the card inside it is solid and lifted.
   That difference is what makes the nesting read as deliberate. */
.panel-cta {
  justify-content: center;
}

.panel-cta .hero-card {
  /* Solid, and lifted. The panel behind it is translucent and barely there;
     this is the thing the page is for, so it stops sharing a surface quality
     with its container and reads as sitting on top of it. */
  background: #ffffff;
  border: 1px solid rgba(17, 18, 20, 0.10);
  box-shadow: 0 14px 40px rgba(17, 18, 20, 0.10),
              0 2px 6px rgba(17, 18, 20, 0.04);
  padding: var(--s6) var(--s5);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}


/* ==========================================================================
   NARROW — fall back to the conversation and the card, stacked
   ========================================================================== */
@media (max-width: 1000px) {
  /* Two screens of scroll, and the grid sticks for all of it — exactly what
     index.html does. The card stops being a third column and becomes an
     overlay in the middle of the screen. */
  body.three .scroller {
    height: 200vh;
    height: 200dvh;
  }
  body.three .scroll-hint { display: block; }

  .grid {
    position: sticky;
    top: 0;
    display: block;
    height: 100vh;
    height: 100dvh;
    min-height: 0;
    width: var(--column);
    max-width: 100%;
    margin: 0 auto;
    padding: var(--s5) var(--s4);
    overflow: hidden;
  }

  .panel-graph { display: none; }

  /* One column has nothing to be bounded against, so the surfaces come off. */
  .panel {
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
  }
  /* On one column the hero card is the only surface, so it goes back to glass
     over the thread — see style.css. */
  .panel-cta .hero-card {
    background: var(--glass);
    padding: var(--s6) var(--s5) var(--s5);
  }

  /* The conversation fills the screen and sits on the bottom, the way a real
     thread does. */
  /* The header and the conversation move as one block, centred in the screen.
     The thread used to be stretched to the full height with its messages
     pinned to the bottom, so a tall phone dropped all of its spare height in
     one lump between the header and the first message. Centring the pair
     splits that height above and below instead, and keeps the header sitting
     on the conversation rather than stranded at the top of the screen. */
  .panel-thread {
    height: 100%;
    justify-content: center;
  }
  .panel-thread .thread {
    height: auto;
    flex: 0 1 auto;            /* as tall as the messages, not the screen */
    justify-content: flex-end;
    padding-bottom: var(--s8);
  }

  /* The card lifts over the middle rather than sitting under everything. */
  .panel-cta {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    padding: var(--s4);
    pointer-events: none;
  }
  .panel-cta .hero-card {
    pointer-events: auto;
    width: 100%;
    /* The thread is behind it again here, so the frost comes back on. */
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(150%);
    backdrop-filter: blur(var(--glass-blur)) saturate(150%);
    background: var(--glass);
  }
}


/* The button, lit from the top. Two stops of one blue — the shading a real
   surface has, rather than a colour transition. */
body.three .hero-cta {
  background: linear-gradient(180deg, #3d7bf8, #2560e8);
}
