/* ---------- TITAN AI ----------
   The plain AI chat. Every value is a token and every size comes off the
   --t-* scale (CLAUDE.md, the theme law and the type scale): there is not a
   raw colour or a hand-picked font size in this file, and no room markup in
   this lane carries a style attribute.

   MARK'S LOOK RULES, BINDING HERE:
     the house body face everywhere, and no mono type on a kicker, a chip or
     a press;
     no pills and no filled blue in the left column, and the accent on
     exactly two things there, the open project and the open chat;
     nothing fake on screen, so there is no rule in this file for a control
     the room does not draw.

   The house classes do the heavy lifting: .btn and its modifiers are the
   presses, .chip and .chip-on are the two chips under the composer, .field
   is every box, and .panel .panel-float is both windows. What is here is the
   GEOMETRY those parts stand in, which is what a room stylesheet is for. */

/* ---------- the stage ----------
   A column that fills the canvas, in two states, and the two are the reason
   this block reads the way it does.

   ON AN EMPTY STAGE THE WHOLE GROUP IS CENTRED, TOGETHER: the spark, the
   greeting, the sub line, the composer card and START WITH A COACH stand as
   one block in the middle of the canvas, which is the reference screen's own
   arrangement (HBP-TITAN-SCREEN.md). The first run drew it the other way, the
   hero floating in the middle and the card pinned at the very foot with a
   canyon of empty canvas between them (tools/titan/titan-room.png,
   2026-09-03), because the log was told to take every spare pixel whether
   there was anything in it or not. So the log only GROWS once there is a
   conversation; empty, it takes its content's height and the column's own
   justify-content:center puts the three parts in the middle together.

   ONCE A THREAD IS OPEN the log takes the height back, the rows fill it from
   the top, and the card is at the foot where a composer belongs. It is one
   layout in two states rather than two layouts, which is what keeps the box a
   person is typing in from being torn out of the document by the paint that
   opens a thread.

   tools/titan/walk-stage.mjs measures the gap: with no thread the card's top
   edge sits just under the sub line, and the group's own middle is the
   canvas's middle. */
.titan{
  display:flex; flex-direction:column; height:100%; min-height:0;
  gap:var(--s5); padding:var(--s5) var(--s6) var(--s6);
  justify-content:center;
}
.titan-log{
  flex:0 1 auto; min-height:0; overflow-y:auto;
  display:flex; flex-direction:column; gap:var(--s6);
  /* the thread is a reading column, not a full-bleed row of text */
  width:100%; max-width:760px; margin:0 auto;
}
/* Once there is a conversation the log takes every spare pixel and the rows
   start at the top of the scroller rather than floating: justify-content on a
   scrolling column would push the oldest line out of reach at the top, so
   this is the safe half of it. */
.titan-open{ justify-content:flex-start; }
.titan-open .titan-log{ flex:1 1 auto; justify-content:flex-start; }

/* ---------- the hero ----------
   The four-point spark, the greeting in the house display face, and one line
   under it. It carries NO auto margin of its own: the stage column above
   centres the whole empty-state group, hero and card and coach block
   together, and an auto margin here would push the card away from the words
   it belongs under, which is exactly what the first run drew.

   THE SPARK IS 34 PIXELS, which is the reference screen's own size, and the
   size lives HERE rather than on the SVG so the same glyph can be small on a
   chip and large here without a second copy of it. */
.titan-hero{
  display:flex; flex-direction:column; align-items:center; gap:var(--s4);
  padding:var(--s4) 0 0; text-align:center;
}
.titan-hero-mark{
  display:flex; align-items:center; justify-content:center;
  width:34px; height:34px; color:var(--accent);
}
.titan-hero-mark svg{ width:100%; height:100%; }
.titan-greet-line{
  margin:0; font-family:var(--font-trajan); font-size:var(--t-room);
  font-weight:var(--w-med); letter-spacing:var(--ls-head); color:var(--text);
}
.titan-greet-note{ margin:0; font-size:var(--t-lead); color:var(--muted); }

/* ---------- start with a coach ----------
   A kicker, a pill and, with a coach picked, four chips in a 2x2 grid. The
   kicker is the house face with the label letter spacing: no mono anywhere on
   this stage (Mark's rule), kickers included. */
.titan-coach{
  flex:none; display:flex; flex-direction:column; align-items:center; gap:var(--s3);
  width:100%; max-width:760px; margin:0 auto; padding-bottom:var(--s5);
}
.titan-kicker{
  font-family:var(--font-ui); font-size:var(--t-label); font-weight:var(--w-semi);
  letter-spacing:var(--ls-label); text-transform:uppercase; color:var(--muted);
}
.titan-coach-pill{
  display:inline-flex; align-items:center; gap:var(--s2);
  padding:var(--s2) var(--s4);
  border:var(--bd) solid var(--edge); border-radius:var(--r-pill);
  background:transparent; color:var(--ink2);
  font-family:var(--font-ui); font-size:var(--t-small); line-height:1;
  transition:color var(--mo-fast), border-color var(--mo-fast);
}
.titan-coach-pill:hover{ color:var(--text); border-color:var(--ink4); }

/* The 2x2 grid of starters. Each is a title and the whole prompt under it, so
   nobody presses one without knowing what it will say; the words wrap rather
   than clipping, because a starter a person cannot read whole is a starter
   they will not press. */
.titan-starters{
  display:grid; grid-template-columns:1fr 1fr; gap:var(--s3);
  width:100%; margin-top:var(--s2);
}
.titan-starter{
  display:flex; flex-direction:column; align-items:flex-start; gap:var(--s1);
  white-space:normal; text-align:left; font-size:var(--t-small);
}
.titan-starter-title{ font-weight:var(--w-semi); color:var(--text); }
.titan-starter-sub{
  font-size:var(--t-tiny); color:var(--muted); line-height:var(--lh-tight);
}

/* ---------- the two kinds of line ----------
   A you line is a block on the right, held to a share of the column so a long
   ask does not become the whole width; an ai line is prose on the left with
   the mind's name over it. */
/* A PLAIN BLOCK, NOT A BUBBLE. Mark's rule against pills is about the left
   column, and the same taste applies here: a filled capsule of somebody's own
   words is chat-app furniture. What tells a you line from an answer is where
   it sits and what weight it carries, which is enough. A hairline edge holds
   it together without making it a badge, and there is no fill at all. */
.titan-you{ display:flex; justify-content:flex-end; }
.titan-you-text{
  max-width:80%; padding:var(--s3) var(--s5);
  border-left:var(--bd-thick) solid var(--edge);
  color:var(--text); font-weight:var(--w-med);
  font-size:var(--t-body); line-height:var(--lh-body); white-space:pre-wrap;
}
.titan-ai{ display:flex; flex-direction:column; gap:var(--s2); }
/* THE HEADER OVER AN ANSWER: the house spark, then the mind's short name and
   its vendor word. Small and muted, in the house face, never mono. There is
   no vendor LOGO anywhere here on purpose (rooms/titan-turns.js says why):
   every answer wears the same honest house mark and says whose model it was
   in words. */
.titan-ai-who{
  display:flex; align-items:center; gap:var(--s2);
  font-size:var(--t-tiny); color:var(--muted);
}
.titan-who-spark{
  display:inline-flex; flex:none; width:13px; height:13px; color:var(--accent);
}
.titan-who-spark svg{ width:100%; height:100%; }
.titan-who-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* THE COACH TRACE, under the answer it grounded, with the same spark. It is
   drawn only when a coach really rode the turn, so it is never a claim. */
.titan-trace{
  display:flex; align-items:center; gap:var(--s2);
  font-size:var(--t-label); color:var(--muted);
}

/* ---------- the one action under an answer ----------
   COPY, AND NOTHING ELSE. Save and Ask another AI to review are later lanes
   and are not drawn at all. Icon only, quiet at rest and lit on hover, so a
   column of answers is not a column of buttons; the accent arrives only when
   the copy actually landed. */
.titan-acts{ display:flex; align-items:center; gap:var(--s2); margin-top:var(--s1); }
.titan-act{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; padding:0;
  border:0; border-radius:var(--r-sm); background:transparent; color:var(--muted);
  transition:color var(--mo-fast), background var(--mo-fast);
}
.titan-act:hover{ color:var(--text); background:var(--sel); }
.titan-act-ok,.titan-act-ok:hover{ color:var(--accent); }
/* ---------- THE PRESS SPEAKS FOR A MOMENT ----------
   Mark copied an answer on the live room and saw nothing change
   (2026-09-04): the swap was the glyph and the title, and a title is a
   tooltip nobody waits for while one small line replaces another under their
   thumb. So while S.titanCopied names this message the press wears the word
   as well as the check, and the square gives up its fixed width for as long
   as that lasts. The room repaints on the press and again when the flag
   clears (actions/titan-stage.js set()s both), so the widening and the
   narrowing are both a paint and never a transition on a box nobody
   measured.

   THE WORD IS THE HOUSE BODY FACE at --t-tiny off the token scale, which is
   the size every other small line in this column wears, and it inherits the
   press's own colour so the landed state is the accent and the refusal is
   the quiet one. Nothing here is a pill and nothing carries a fill. */
.titan-act-said{
  width:auto; gap:var(--s2); padding:0 var(--s3);
  font-family:inherit; font-size:var(--t-tiny); font-weight:var(--w-med);
}
.titan-act-word{ white-space:nowrap; }
.titan-ai-body{ color:var(--ink2); font-size:var(--t-body); line-height:var(--lh-read); }
.titan-ai-body > :first-child{ margin-top:0; }
.titan-ai-body > :last-child{ margin-bottom:0; }
.titan-ai-body p{ margin:0 0 var(--s5); }
.titan-ai-body h3{
  margin:var(--s6) 0 var(--s3); font-size:var(--t-sub);
  font-weight:var(--w-semi); color:var(--text); letter-spacing:var(--ls-head);
}
.titan-ai-body h4{
  margin:var(--s5) 0 var(--s2); font-size:var(--t-lead);
  font-weight:var(--w-semi); color:var(--text);
}
.titan-ai-body ul,.titan-ai-body ol{ margin:0 0 var(--s5); padding-left:var(--s7); }
.titan-ai-body li{ margin:0 0 var(--s2); }
.titan-ai-body strong{ color:var(--text); font-weight:var(--w-semi); }
.titan-ai-body code{
  padding:1px var(--s1); border-radius:var(--r-sm);
  background:var(--inset); font-family:var(--font-mono); font-size:var(--t-small);
}
/* A code BLOCK is the one place mono type belongs: it is code, not a label. */
.titan-ai-body pre{
  margin:0 0 var(--s5); padding:var(--s4) var(--s5); overflow-x:auto;
  border:var(--bd) solid var(--edge); border-radius:var(--r-md); background:var(--inset);
}
.titan-ai-body pre code{
  padding:0; background:none; font-size:var(--t-small); line-height:var(--lh-body);
}

.titan-thinking{ font-size:var(--t-tiny); color:var(--muted); }
/* A note on a done line (an answer that was cut short) sits under it, quiet. */
.titan-note{ font-size:var(--t-tiny); color:var(--muted); }
.titan-error{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--s3);
  padding:var(--s4) var(--s5); border:var(--bd) solid var(--edge);
  border-radius:var(--r-md); background:var(--inset);
  color:var(--muted); font-size:var(--t-small); line-height:var(--lh-body);
}
.titan-error-go{ flex:none; }

/* ---------- the composer card ----------
   A rounded, shadowed box holding the field and one row of controls. It is
   the same 760 pixel reading column as the thread, so the box lines up with
   the words it answers, and it is the ONE card on this stage: everything else
   here is prose on the canvas.

   ON AN EMPTY STAGE IT SITS UNDER THE HERO, in the middle of the canvas; with
   a conversation open the log takes the height and the card falls to the
   foot. Neither is a second card: the open state only changes what is above
   it. */
.titan-composer{
  flex:none; display:flex; flex-direction:column;
  width:100%; max-width:760px; margin:0 auto;
}
.titan-card{
  display:flex; flex-direction:column; gap:var(--s3);
  padding:var(--s4) var(--s4) var(--s3);
  border:var(--bd) solid var(--edge); border-radius:var(--r-xl);
  background:var(--panel); box-shadow:var(--sh-card);
}
/* The field inside the card carries none of its own frame: the card IS the
   frame, and a box inside a box reads as two. The height is set by the arm,
   which measures what the text actually took at this width; the cap here is
   the scroll it falls back to. */
.titan-box{
  max-height:180px; resize:none; overflow-y:auto;
  padding:var(--s2) var(--s2) 0;
  border:0; background:transparent;
  line-height:var(--lh-body); font-family:var(--font-ui); font-size:var(--t-body);
}
.titan-box:focus{ outline:none; box-shadow:none; }
/* The note after an attach: one line, six seconds, then it goes. */
.titan-attach-note{ padding:0 var(--s2); font-size:var(--t-tiny); color:var(--muted); }

.titan-card-row{ display:flex; align-items:center; gap:var(--s2); }
.titan-card-gap{ flex:1 1 auto; }

/* ---------- the two chips on the card ----------
   A mark, a word and a chevron. They read as chips and not as pills, in the
   house face at the house size: no mono on a chip (Mark's rule). The web chip
   is LIT unless it is Off, which is the one place the accent lands on this
   row besides the send seat. */
.titan-chip{
  display:inline-flex; align-items:center; gap:var(--s2); flex:0 1 auto; min-width:0;
  padding:var(--s2) var(--s3);
  border:var(--bd) solid var(--edge); border-radius:var(--r-pill);
  background:transparent; color:var(--ink3);
  font-family:var(--font-ui); font-size:var(--t-tiny); line-height:1;
  transition:color var(--mo-fast), border-color var(--mo-fast);
}
.titan-chip:hover{ color:var(--text); border-color:var(--ink4); }
.titan-chip-on{ color:var(--accent); border-color:var(--accent); }
.titan-chip-on:hover{ color:var(--accent); border-color:var(--accent); }
.titan-chip-off{ opacity:.45; cursor:not-allowed; }
.titan-chip-off:hover{ color:var(--ink3); border-color:var(--edge); }
.titan-chip-word{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.titan-chip-mark{ display:inline-flex; flex:none; width:14px; height:14px; }
.titan-chip-mark svg{ width:100%; height:100%; }
.titan-chevron{ display:inline-flex; flex:none; width:12px; height:12px; color:var(--muted); }
.titan-chevron svg{ width:100%; height:100%; }

/* A SLOW, SUBTLE PULSE ON THE SPARK WHILE A TURN IS IN FLIGHT. It is the one
   moving thing on the stage and it is deliberately almost nothing: a spinner
   in the chip would compete with the thinking line, and a still mark would
   leave the room looking asleep while it works. */
@keyframes titan-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.4; } }
.titan-pulse{ animation:titan-pulse 2.4s ease-in-out infinite; }
@media (prefers-reduced-motion:reduce){ .titan-pulse{ animation:none; } }

/* ---------- the two round seats ----------
   The paperclip and the send arrow. Both are circles, which is what
   --r-round is; the send seat wears the accent and the paperclip is quiet,
   because one of them is the room's one job and the other is a side door.

   SEND IS NEVER DISABLED and there is no rule here that greys it: an empty
   press does nothing at all, which is quieter than a button that dies under
   somebody mid-thought.

   THE PAPERCLIP IS A LABEL AROUND A FILE INPUT, which is the browser's own
   way to put a face on one, so the input itself is taken out of the layout
   and the word inside it is read by a screen reader and by nothing else. */
.titan-round{
  display:inline-flex; align-items:center; justify-content:center; position:relative;
  flex:none; width:32px; height:32px; padding:0;
  border:0; border-radius:var(--r-round);
  transition:color var(--mo-fast), background var(--mo-fast), filter var(--mo-fast);
}
.titan-round svg{ width:17px; height:17px; }
.titan-round-quiet{ background:transparent; color:var(--muted); cursor:pointer; }
.titan-round-quiet:hover{ background:var(--sel); color:var(--text); }
.titan-round-go{ background:var(--accent); color:var(--onAccent); }
.titan-round-go:hover{ filter:brightness(1.08); }
.titan-round-mark{ display:inline-flex; }
/* The label's own words, for a screen reader only: the glyph is the face. */
.titan-round-word,.titan-file{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap;
}
/* The off-screen box the copy fallback selects when the clipboard API is not
   there. It has to be IN the document to be selectable, so it is hidden by
   size rather than by display none. */
.titan-clip-hidden{
  position:fixed; top:0; left:0; width:1px; height:1px;
  opacity:0; border:0; padding:0;
}

/* ---------- a picker window's rows ----------
   One shape for all three windows (rooms/titan-picker.js says why). A group
   heading, then rows carrying a name, up to two sub lines, the cost dollars
   at the right and a check on the one that is on. Everything in the house
   face: a list of company names set in mono would read as a config file. */
.titan-pick-body{
  display:flex; flex-direction:column; gap:1px;
  max-height:min(60vh, 520px); overflow-y:auto;
}
.titan-pick-group{
  padding:var(--s5) var(--s3) var(--s2);
  font-family:var(--font-ui); font-size:var(--t-label); font-weight:var(--w-semi);
  letter-spacing:var(--ls-label); text-transform:uppercase; color:var(--muted);
}
.titan-pick-group:first-child{ padding-top:0; }
.titan-pick-row{
  display:flex; align-items:center; gap:var(--s3);
  padding:var(--s3) var(--s4);
  border:var(--bd) solid transparent; border-radius:var(--r-md);
  background:transparent; color:var(--ink2); text-align:left;
  font-family:var(--font-ui); transition:background var(--mo-fast), color var(--mo-fast);
}
.titan-pick-row:hover{ background:var(--sel); color:var(--text); }
.titan-pick-row-on{ color:var(--accent); }
.titan-pick-row-on:hover{ color:var(--accent); }
.titan-pick-left{
  display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  flex:1 1 auto; min-width:0;
}
.titan-pick-name{ font-size:var(--t-small); font-weight:var(--w-med); }
.titan-pick-sub{ font-size:var(--t-tiny); color:var(--muted); line-height:var(--lh-tight); }
.titan-pick-cost{ flex:none; font-size:var(--t-tiny); color:var(--muted); }
.titan-pick-row-on .titan-pick-cost{ color:var(--accent); }
.titan-pick-tick{ display:inline-flex; flex:none; color:var(--accent); }
/* THE DISCLOSURE AT THE FOOT of the model window. Small and quiet, and it
   stays: it is the one place the room says out loud that the answer can be
   wrong. */
.titan-pick-foot{
  padding-top:var(--s4); border-top:var(--bd) solid var(--edge);
  font-size:var(--t-label); color:var(--muted); line-height:var(--lh-body);
}

/* ---------- the left column ----------
   Plain rows. No mono, no pills, no filled blue, and the accent on exactly the
   open project and the open chat. A row is a press and its second act (the pin
   or the archive cross) appears on hover, so the resting column is quiet; the
   act is always in the markup, so a keyboard reaches it. */
.titan-side{ display:flex; flex-direction:column; gap:var(--s6); padding:var(--s4) var(--s3) var(--s6); }
.titan-side-block{ display:flex; flex-direction:column; gap:1px; }
.titan-side-head{
  padding:var(--s4) var(--s4) var(--s2);
  font-family:var(--font-ui); font-size:var(--t-tiny); font-weight:var(--w-semi);
  color:var(--muted);
}
.titan-side-quiet{ padding:var(--s3) var(--s4); font-size:var(--t-tiny); color:var(--muted); }
.titan-side-press{ margin:var(--s2) 0; font-size:var(--t-small); }

.titan-row-wrap{ position:relative; display:flex; align-items:stretch; }
.titan-row{
  flex:1 1 auto; min-width:0;
  display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  padding:var(--s3) var(--s4); border:var(--bd) solid transparent; border-radius:var(--r-md);
  background:transparent; color:var(--ink3); text-align:left;
  font-family:var(--font-ui); font-size:var(--t-small); line-height:var(--lh-tight);
  transition:background var(--mo-fast), color var(--mo-fast);
}
.titan-row:hover{ background:var(--sel); color:var(--text); }
/* THE ACCENT ON THE OPEN THING, and as ink rather than as a fill. */
.titan-row-on{ color:var(--accent); }
.titan-row-on:hover{ color:var(--accent); }
.titan-row-name{
  display:flex; align-items:center; gap:var(--s2);
  width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.titan-row-pin{ display:inline-flex; flex:none; color:var(--muted); }
.titan-row-on .titan-row-pin{ color:var(--accent); }
.titan-row-kind,.titan-row-when{ font-size:var(--t-label); color:var(--muted); }

.titan-row-act{
  flex:none; display:flex; align-items:center; justify-content:center;
  width:26px; margin-left:var(--s1); padding:0;
  border:0; border-radius:var(--r-md); background:transparent; color:var(--muted);
  opacity:0; transition:opacity var(--mo-fast), color var(--mo-fast);
}
.titan-row-wrap:hover .titan-row-act,
.titan-row-act:focus-visible{ opacity:1; }
.titan-row-act:hover{ color:var(--text); background:var(--sel); }

/* ---------- the right column's Project shelf ---------- */
.titan-tool{ display:flex; flex-direction:column; gap:var(--s4); padding:var(--s5); }
.titan-tool-title{ font-size:var(--t-lead); font-weight:var(--w-semi); color:var(--text); }
.titan-tool-kind{ font-size:var(--t-tiny); color:var(--muted); }
.titan-tool-note{ font-size:var(--t-small); color:var(--muted); line-height:var(--lh-body); }
.titan-tool-field{ display:flex; flex-direction:column; gap:var(--s2); }
.titan-tool-label{ font-size:var(--t-tiny); font-weight:var(--w-semi); color:var(--muted); }
.titan-tool-box{ resize:vertical; font-family:var(--font-ui); }
.titan-tool-saved{ font-size:var(--t-label); color:var(--muted); }

/* ---------- the two windows ----------
   The house floating window, sized for what each holds. .panel-float and the
   scrim are components.css's; the modal law's own parts (data-drag, the cross)
   are in the markup. */
.titan-win{ width:min(560px, 92vw); gap:var(--s5); }
.titan-win-small{ width:min(420px, 92vw); }
.titan-win-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:var(--s4); }
.titan-win-title{ font-size:var(--t-head); font-weight:var(--w-semi); color:var(--text); }
.titan-win-note{ margin-top:var(--s1); font-size:var(--t-small); color:var(--muted); }

/* On a phone the reading column is the screen and the starters stack. */
@media (max-width:900px){
  .titan{ padding:var(--s4); }
  .titan-you-text{ max-width:92%; }
  .titan-chip{ max-width:44%; }
  /* Four chips side by side on a phone is four unreadable chips, so the 2x2
     grid becomes one column and each starter gets the whole width. */
  .titan-starters{ grid-template-columns:1fr; }
}
