/* ════════════════════════════════════════════════════════════════════════
   COSMOS V2 — TOKENS
   ────────────────────────────────────────────────────────────────────────
   The system has two orthogonal dimensions:

     1. AMBIENCE  → night | dawn | day | dusk
        A circadian primitive. Sets the overall light temperature, ground
        color, sky gradient, particulate density, type contrast tier, and
        node luminance curve. Day is light. The other three are dark.

     2. KIND      → self | observed | inferred | person | cosmos
        Semantic meaning of a node or piece of content. Each kind has
        its own light color (a hue, not a fill). The same kind looks
        slightly different across ambiences — like the same star at
        different times of night.

   To switch ambience, set `data-ambience="day"` on the root element.
   All tokens cascade.
   ════════════════════════════════════════════════════════════════════════ */

/* Self-hosted variable fonts. Replaces the Google Fonts CDN @import so the
   page paints without a network round-trip to fonts.googleapis.com, works
   offline, and stays uncensored if CF Bot Fight Mode ever filters the CDN
   crawler. Files committed to /fonts/ from the cosmos-design-system kit. */
@font-face {
  font-family: 'Fraunces';
  src: url('/fonts/Fraunces-Variable.woff2') format('woff2-variations'),
       url('/fonts/Fraunces-Variable.woff2') format('woff2');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Mona Sans';
  src: url('/fonts/MonaSans-Variable.woff2') format('woff2-variations'),
       url('/fonts/MonaSans-Variable.woff2') format('woff2');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/JetBrainsMono-Variable.woff2') format('woff2-variations'),
       url('/fonts/JetBrainsMono-Variable.woff2') format('woff2');
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}

/* ─── KIND HUES (graph node colors) ────────────────────────────────────
   These are HUE references. Components compose them with ambience-driven
   alpha to produce the actual rendered light. Don't fill nodes with
   these directly — pass them through the radial halo formulas.            */
:root {
  --kind-self:     #E8C5A0;   /* warm sand — what you said */
  --kind-observed: #7FEDC7;   /* mint — what cosmos saw */
  --kind-inferred: #C5A8FF;   /* lavender — patterns */
  --kind-person:   #FF9EC4;   /* soft rose — people */
  --kind-cosmos:   #9FB8FF;   /* periwinkle — the entity */

  /* Edge tints — opaque hues only. Opacity is applied by the renderer. */
  --edge-tint-grounds:    #FFB47A;
  --edge-tint-causes:     #C8D8FF;
  --edge-tint-enables:    #7FEDC7;
  --edge-tint-blocks:     #FF6E82;
  --edge-tint-resonates:  #C8A8FF;

  /* ─── TYPE FAMILIES ──────────────────────────────────────────────────
     Cosmos speaks in serif. The user speaks in sans.
     Mono is rare — only for timestamps and keyboard hints. No mono labels.
  */
  --font-cosmos: 'Fraunces', 'GT Sectra', 'Tiempos Headline', Georgia, serif;
  --font-self:   'Mona Sans', 'GT America', system-ui, -apple-system, sans-serif;
  --font-meta:   'JetBrains Mono', ui-monospace, Menlo, monospace;

  /* Optical sizing for the serif (Fraunces is variable) */
  --font-cosmos-opsz-display: 'opsz' 96, 'SOFT' 50, 'WONK' 0;
  --font-cosmos-opsz-body:    'opsz' 14, 'SOFT' 100, 'WONK' 0;
  --font-cosmos-opsz-glyph:   'opsz' 144, 'SOFT' 100, 'WONK' 1;

  /* ─── MOTION ─────────────────────────────────────────────────────────
     Restrained, organic, never bouncy.                                    */
  --ease-soft:     cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-stage:    cubic-bezier(0.32, 0.72, 0, 1);
  --dur-fast: 180ms;
  --dur-base: 320ms;
  --dur-slow: 720ms;
  --dur-breath: 5200ms;     /* slower than v1; the field doesn't fidget */
  --dur-drift: 24000ms;

  /* Hairline color matched to the polish layer on the landing + /me.
     Components draw their 1px ring with inset box-shadow at this color,
     not a real border. Keeps geometry exact when widths change. */
  --ink-line: rgba(255, 255, 255, 0.08);
  --signal:   #7FEDC7;
}

/* ════════════════════════════════════════════════════════════════════════
   AMBIENCE: NIGHT  (default — 21:00–06:00)
   ─── deep cosmos, near-black with cyan-teal undertone, peak node luminance
   ════════════════════════════════════════════════════════════════════════ */
:root,
[data-ambience="night"] {
  --ambience: night;

  /* ground & sky — the page is a vertical gradient, never flat */
  --bg-ground:   #04060c;
  --bg-mid:      #06090f;
  --bg-sky:      #080d18;
  --bg-overlay:  radial-gradient(ellipse 80% 50% at 50% 38%,
                   rgba(40, 90, 140, 0.10) 0%,
                   transparent 65%);
  --bg-stars:    rgba(255, 255, 255, 0.55);   /* visible at this ambience */
  --bg-stars-density: 1;                       /* multiplier for star count */
  --haze:        rgba(8, 13, 24, 0.55);        /* distance fog color */

  /* type — high contrast against deep dark */
  --ink-1: rgba(255, 255, 255, 0.96);   /* highest */
  --ink-2: rgba(255, 255, 255, 0.74);
  --ink-3: rgba(255, 255, 255, 0.46);
  --ink-4: rgba(255, 255, 255, 0.22);

  /* node light — saturated, halos far-reaching */
  --node-luminance: 1;          /* multiplier */
  --node-halo-radius: 1.3;       /* multiplier on base radius */
  --node-saturation: 1;

  /* the input filament */
  --filament: linear-gradient(90deg,
    transparent 0%,
    rgba(127, 231, 220, 0.10) 20%,
    rgba(127, 231, 220, 0.55) 50%,
    rgba(127, 231, 220, 0.10) 80%,
    transparent 100%);
  --filament-width: 1px;

  /* the only "card" surface — used very rarely. mostly we don't use it. */
  --whisper-bg: rgba(8, 12, 22, 0.40);
  --whisper-edge: rgba(127, 231, 220, 0.10);

  --surface-edge:   rgba(255, 255, 255, 0.06);  /* dividers, subtle borders */
  --surface-inset:  rgba(255, 255, 255, 0.03);  /* inset sub-surfaces, tags */
  --overlay-bg:     rgba(4, 6, 12, 0.72);       /* modal/screen backdrops */
  --edge-line:      rgba(205, 218, 245, 0.28);  /* graph edges — silver-blue starlight */

  color-scheme: dark;
}

/* ════════════════════════════════════════════════════════════════════════
   AMBIENCE: DAWN  (06:00–10:00)
   ─── pale cool fog, low contrast, rose-gold accents, stars fading
   ════════════════════════════════════════════════════════════════════════ */
[data-ambience="dawn"] {
  --ambience: dawn;
  --bg-ground:   #1a2233;
  --bg-mid:      #2c3a52;
  --bg-sky:      #485f7e;
  --bg-overlay:  radial-gradient(ellipse 90% 60% at 30% 90%,
                   rgba(255, 168, 140, 0.18) 0%,
                   transparent 50%),
                 radial-gradient(ellipse 70% 50% at 70% 0%,
                   rgba(180, 200, 240, 0.20) 0%,
                   transparent 60%);
  --bg-stars:    rgba(255, 230, 220, 0.18);   /* fading */
  --bg-stars-density: 0.4;
  --haze:        rgba(72, 95, 126, 0.55);

  --ink-1: rgba(255, 248, 244, 0.94);
  --ink-2: rgba(255, 245, 240, 0.66);
  --ink-3: rgba(255, 245, 240, 0.40);
  --ink-4: rgba(255, 245, 240, 0.20);

  --node-luminance: 0.7;
  --node-halo-radius: 1.6;       /* halos diffuse more in atmosphere */
  --node-saturation: 0.85;

  --filament: linear-gradient(90deg,
    transparent 0%,
    rgba(180, 210, 255, 0.14) 30%,
    rgba(210, 228, 255, 0.48) 50%,
    rgba(180, 210, 255, 0.14) 70%,
    transparent 100%);

  --whisper-bg: rgba(20, 28, 44, 0.30);
  --whisper-edge: rgba(180, 210, 255, 0.16);

  --surface-edge:   rgba(200, 220, 255, 0.10);
  --surface-inset:  rgba(255, 245, 240, 0.04);
  --overlay-bg:     rgba(10, 16, 28, 0.72);
  --edge-line:      rgba(200, 218, 248, 0.18);  /* cool morning mist */

  color-scheme: dark;
}

/* ════════════════════════════════════════════════════════════════════════
   AMBIENCE: DAY  (10:00–17:00)
   ─── outdoors-but-indoors. warm off-white sky overhead, gentle ground.
   nodes become glass orbs, less self-luminous.
   ════════════════════════════════════════════════════════════════════════ */
[data-ambience="day"] {
  --ambience: day;
  --bg-ground:   #f0ece2;       /* warm parchment, not white */
  --bg-mid:      #e8e4d8;
  --bg-sky:      #cdd6e4;       /* cool sky tint up top */
  --bg-overlay:  radial-gradient(ellipse 100% 70% at 50% -10%,
                   rgba(180, 200, 230, 0.55) 0%,
                   transparent 70%),
                 radial-gradient(ellipse 80% 40% at 50% 110%,
                   rgba(220, 200, 170, 0.40) 0%,
                   transparent 60%);
  --bg-stars:    transparent;    /* no stars during day */
  --bg-stars-density: 0;
  --haze:        rgba(232, 228, 216, 0.55);

  --ink-1: rgba(38, 32, 24, 0.92);
  --ink-2: rgba(38, 32, 24, 0.62);
  --ink-3: rgba(38, 32, 24, 0.38);
  --ink-4: rgba(38, 32, 24, 0.18);

  --node-luminance: 0.55;
  --node-halo-radius: 1.0;
  --node-saturation: 1.05;       /* slightly punchier so nodes don't wash */

  --filament: linear-gradient(90deg,
    transparent 0%,
    rgba(160, 130, 90, 0.20) 30%,
    rgba(160, 130, 90, 0.55) 50%,
    rgba(160, 130, 90, 0.20) 70%,
    transparent 100%);

  --whisper-bg: rgba(255, 252, 245, 0.55);
  --whisper-edge: rgba(160, 130, 90, 0.18);

  --surface-edge:   rgba(160, 130, 90, 0.14);   /* warm amber dividers */
  --surface-inset:  rgba(160, 130, 90, 0.06);   /* warm inset surfaces */
  --overlay-bg:     rgba(240, 236, 226, 0.82);  /* light modal backdrop */
  --edge-line:      rgba(100, 76, 42, 0.42);    /* warm amber thread */

  color-scheme: light;
}

/* ════════════════════════════════════════════════════════════════════════
   AMBIENCE: DUSK  (17:00–21:00)
   ─── gold-violet warm. saturated. most cinematic.
   ════════════════════════════════════════════════════════════════════════ */
[data-ambience="dusk"] {
  --ambience: dusk;
  --bg-ground:   #15101a;
  --bg-mid:      #2a1830;
  --bg-sky:      #4a2548;
  --bg-overlay:  radial-gradient(ellipse 100% 70% at 50% 105%,
                   rgba(255, 140, 90, 0.32) 0%,
                   transparent 55%),
                 radial-gradient(ellipse 80% 50% at 80% 10%,
                   rgba(180, 100, 200, 0.25) 0%,
                   transparent 60%);
  --bg-stars:    rgba(255, 220, 200, 0.32);   /* stars returning */
  --bg-stars-density: 0.7;
  --haze:        rgba(60, 30, 70, 0.50);

  --ink-1: rgba(255, 245, 240, 0.96);
  --ink-2: rgba(255, 240, 230, 0.74);
  --ink-3: rgba(255, 235, 220, 0.46);
  --ink-4: rgba(255, 235, 220, 0.22);

  --node-luminance: 0.95;
  --node-halo-radius: 1.5;
  --node-saturation: 1.15;

  --filament: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 180, 130, 0.16) 25%,
    rgba(255, 180, 130, 0.65) 50%,
    rgba(255, 180, 130, 0.16) 75%,
    transparent 100%);

  --whisper-bg: rgba(40, 22, 50, 0.40);
  --whisper-edge: rgba(255, 180, 130, 0.18);

  --surface-edge:   rgba(255, 235, 220, 0.08);
  --surface-inset:  rgba(255, 235, 220, 0.04);
  --overlay-bg:     rgba(12, 6, 16, 0.75);
  --edge-line:      rgba(215, 158, 232, 0.28);  /* violet evening haze */

  color-scheme: dark;
}

/* ─── Type roles (ambience-aware via --ink-* tokens) ─────────────────── */
.t-cosmos {
  font-family: var(--font-cosmos);
  font-feature-settings: var(--font-cosmos-opsz-body);
  font-weight: 400;
  font-size: 18px;
  line-height: 1.55;
  letter-spacing: -0.005em;
  color: var(--ink-1);
}
.t-cosmos-display {
  font-family: var(--font-cosmos);
  font-variation-settings: 'opsz' 96, 'SOFT' 50;
  font-weight: 400;
  font-size: clamp(34px, 4.6vw, 64px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink-1);
}
.t-cosmos-italic {
  font-family: var(--font-cosmos);
  font-style: italic;
  font-weight: 400;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-1);
}
.t-self {
  font-family: var(--font-self);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--ink-1);
}
.t-self-light {
  font-family: var(--font-self);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-2);
}
.t-meta {
  font-family: var(--font-meta);
  font-weight: 400;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-3);
}

/* ─── Base reset ────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg-ground);
  color: var(--ink-1);
  font-family: var(--font-self);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Prose wrap defaults sync with the landing + /me polish layer.
   Short headings balance, long prose pretty. Components opt in by
   adding these classes or by inheriting through the type roles below. */
.wrap-balance { text-wrap: balance; }
.wrap-pretty  { text-wrap: pretty; }

/* ─── Glass primitive ─── the one surface. every panel uses this.
   Border is drawn as an inset 1px ring so panel geometry never shifts
   by the border width when content swaps. Saturate bumped to 140%
   to match the landing nav material. */
.glass {
  background: var(--whisper-bg);
  border: 0;
  box-shadow:
    inset 0 0 0 1px var(--whisper-edge),
    0 1px 0 rgba(255,255,255,0.06) inset,
    0 24px 60px -20px rgba(0,0,0,0.55);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  border-radius: 6px;
}
.glass-strong { background: rgba(8,12,22,0.62); }

/* Day-mode overrides — panels need more opacity and a soft shadow on light bg */
[data-ambience="day"] .glass {
  background: rgba(255, 252, 245, 0.78);
  box-shadow:
    inset 0 0 0 1px rgba(160, 130, 90, 0.30),
    0 1px 0 rgba(255,255,255,0.60) inset,
    0 8px 32px -8px rgba(80, 60, 30, 0.14);
}

/* Kind-tinted variants re-cast the inset ring at the matching hue.
   Keep the soft drop shadow from .glass; only the ring color shifts. */
.glass-tinted-self     { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-self)     35%, var(--whisper-edge)), 0 1px 0 rgba(255,255,255,0.06) inset, 0 24px 60px -20px rgba(0,0,0,0.55); }
.glass-tinted-observed { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-observed) 30%, var(--whisper-edge)), 0 1px 0 rgba(255,255,255,0.06) inset, 0 24px 60px -20px rgba(0,0,0,0.55); }
.glass-tinted-inferred { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-inferred) 30%, var(--whisper-edge)), 0 1px 0 rgba(255,255,255,0.06) inset, 0 24px 60px -20px rgba(0,0,0,0.55); }
.glass-tinted-person   { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-person)   30%, var(--whisper-edge)), 0 1px 0 rgba(255,255,255,0.06) inset, 0 24px 60px -20px rgba(0,0,0,0.55); }
.glass-tinted-cosmos   { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-cosmos)   25%, var(--whisper-edge)), 0 1px 0 rgba(255,255,255,0.06) inset, 0 24px 60px -20px rgba(0,0,0,0.55); }

/* ─── Panel utilities ─── */
.panel-h {
  font-family: var(--font-meta);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: lowercase;
  color: var(--ink-3);
  line-height: 1;
}
.quiet-btn {
  background: transparent; border: none; padding: 0; cursor: pointer;
  font: inherit; color: inherit;
}
.row { display: flex; align-items: center; gap: 10px; }

/* ─── Breath animation ─── */
@keyframes cosmosBreath {
  0%, 100% { opacity: 0.4; }
  50%       { opacity: 0.9; }
}

@keyframes orbit-rotate {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.breath { animation: cosmosBreath 5.2s ease-in-out infinite; }

/* ─── Blink animation ─── */
@keyframes blink {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0; }
}
.blink { animation: blink 1.2s step-end infinite; }

/* ─── Scroll utility ─── */
.scroll { overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.10) transparent; }
.scroll::-webkit-scrollbar { width: 4px; }
.scroll::-webkit-scrollbar-track { background: transparent; }
.scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.10); border-radius: 2px; }

/* ─── Filament input bar ───
   The composer. Inset-ring border so its geometry stays exact when
   the inner textarea autosizes. Frosted material at blur(20px)
   saturate(140%) to match the landing nav. Focus ring is a second
   inset stroke in --signal, applied via .filament-bar.focused. */
.filament-bar {
  position: relative;
  width: 100%;
  display: flex;
  align-items: flex-end;     /* anchor send button to bottom when textarea grows */
  gap: 12px;
  padding: 10px 14px 10px 18px;
  background: var(--whisper-bg);
  border: 0;
  border-radius: 24px;
  box-shadow: inset 0 0 0 1px var(--whisper-edge);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  transition: box-shadow 240ms var(--ease-out-expo),
              background 240ms var(--ease-out-expo);
}
.filament-bar.focused {
  box-shadow: inset 0 0 0 1px var(--signal);
}
.filament-bar::before {
  content: '';
  position: absolute;
  left: 10%; right: 10%; bottom: -1px;
  height: 1px;
  background: var(--filament);
  filter: blur(0.5px);
  pointer-events: none;
}
.filament-bar input,
.filament-bar textarea {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--ink-1);
  font-family: var(--font-self);
  font-weight: 300;
  font-size: 15px;
  line-height: 1.45;
  resize: none;
  padding: 8px 0;
  /* Native autosize where supported. JS measures scrollHeight as fallback. */
  field-sizing: content;
  min-height: 28px;
  max-height: calc(1.45em * 6 + 16px);
  overflow-y: auto;
  text-wrap: pretty;
}
.filament-bar input::placeholder,
.filament-bar textarea::placeholder {
  color: var(--ink-4);
  font-style: italic;
  font-family: var(--font-cosmos);
}

/* Send affordance. Real 44pt target. Glyph not a word, with the
   keyboard hint underneath the composer (rendered by JS). */
.filament-send {
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  padding: 0;
  background: rgba(127,237,199,0.10);
  border: 0;
  box-shadow: inset 0 0 0 1px rgba(127,237,199,0.28);
  border-radius: 50%;
  color: var(--signal);
  cursor: pointer;
  font-family: var(--font-meta);
  font-size: 14px;
  transition: background 240ms var(--ease-out-expo),
              box-shadow 240ms var(--ease-out-expo),
              transform 240ms var(--ease-out-expo),
              opacity 240ms var(--ease-out-expo);
}
.filament-send:hover:not(:disabled) {
  background: rgba(127,237,199,0.18);
  box-shadow: inset 0 0 0 1px var(--signal);
  transform: translateY(-1px);
}
.filament-send:disabled {
  opacity: 0.35;
  cursor: default;
}

/* Hint row under the composer. Visible on focus, fades on blur. */
.filament-hint {
  display: flex; gap: 16px; justify-content: center; align-items: center;
  margin-top: 8px;
  font-family: var(--font-meta);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-4);
  opacity: 0;
  transition: opacity 240ms var(--ease-out-expo);
  pointer-events: none;
}
.filament-hint.visible { opacity: 1; }
.filament-hint kbd {
  font: inherit; color: var(--ink-3);
  padding: 1px 4px;
  background: transparent;
  border: 0;
  box-shadow: inset 0 0 0 1px var(--ink-line);
  border-radius: 3px;
}

/* ─── Pill button ─── */
.btn-pill {
  font-family: var(--font-self);
  font-weight: 400;
  font-size: 13px;
  padding: 10px 22px;
  min-height: 44px;
  border-radius: 999px;
  border: 0;
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-cosmos) 38%, transparent);
  background: color-mix(in oklab, var(--kind-cosmos) 14%, rgba(8,12,22,0.50));
  color: var(--ink-1);
  cursor: pointer;
  transition: background 240ms var(--ease-out-expo),
              box-shadow 240ms var(--ease-out-expo),
              transform 240ms var(--ease-out-expo);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
}
.btn-pill:hover {
  background: color-mix(in oklab, var(--kind-cosmos) 22%, rgba(8,12,22,0.60));
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--kind-cosmos) 60%, transparent),
              0 0 24px -4px color-mix(in oklab, var(--kind-cosmos) 60%, transparent);
  transform: translateY(-1px);
}

/* ─── Chip ─── */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 9px 4px 7px;
  font-family: var(--font-self);
  font-weight: 300;
  font-size: 12px;
  background: rgba(8,12,22,0.50);
  border: 0;
  box-shadow: inset 0 0 0 1px var(--ink-line);
  border-radius: 999px;
  color: var(--ink-1);
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
  cursor: pointer;
  transition: box-shadow 240ms var(--ease-out-expo),
              background 240ms var(--ease-out-expo);
}
.chip:hover { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18); }

/* Chat surface prose. Assistant bubbles get pretty wrap so widows
   don't cluster at line breaks. Headings (sender names, thread titles,
   one-line meta) balance for symmetric line lengths. */
.chat-assistant-text,
.t-cosmos,
.t-cosmos-italic { text-wrap: pretty; }

.chat-heading,
.t-meta { text-wrap: balance; }

/* Message column constraint. Used by chat-message wrappers so prose
   stays at a reading width on big screens and snaps to the right
   padding on phones. */
.chat-column {
  width: 100%;
  max-width: min(60ch, 720px);
  margin: 0 auto;
  padding-left: 24px;
  padding-right: 24px;
}
@media (max-width: 640px) {
  .chat-column { padding-left: 16px; padding-right: 16px; }
}

/* Streaming cursor — a thin glyph after the live assistant text.
   Hidden when prefers-reduced-motion is set (animation override below). */
.streaming-cursor {
  display: inline-block;
  width: 2px; height: 1em;
  margin-left: 2px;
  vertical-align: -0.15em;
  background: currentColor;
  opacity: 0.85;
  animation: streamCursorBlink 1.05s steps(2) infinite;
}
@keyframes streamCursorBlink {
  0%, 100% { opacity: 0.85; }
  50%      { opacity: 0; }
}

/* Cursor keyframe used by the mobile filament value preview. Lives
   in tokens.css because cosmos.html does not load cosmos.css where
   the original definition sits. */
@keyframes cursorBlink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .streaming-cursor { animation: none; opacity: 0.6; }
  .breath { animation: none; opacity: 0.7; }
}

/* ─── Mobile fallbacks ──────────────────────────────────────────────────
   The cosmos-app React surface is desktop-first. These rules tighten
   the visible shells (filament bar, panels, chips, btn-pill) at phone
   widths so absolute-width primitives do not push past the viewport.
   Component-specific widths set inline in cosmos-app.js may still
   override; this is a safety net, not a redesign. */
@media (max-width: 680px) {
  .filament-bar {
    padding: 8px 10px 8px 16px;
    font-size: 16px;       /* 16px prevents iOS Safari auto-zoom on focus */
  }
  .filament-bar input,
  .filament-bar textarea {
    font-size: 16px;
  }
  .panel-h {
    padding: 14px 16px;
  }
  .btn-pill {
    padding: 10px 18px;
    min-height: 44px;
    font-size: 13px;
  }
  .chip {
    padding: 4px 8px 4px 6px;
    font-size: 11px;
  }
}

@media (max-width: 480px) {
  /* Stop horizontal scroll bleed from inline-styled fixed-width
     elements common in cosmos-app. */
  body { overflow-x: hidden; }
}
