/* A small Patchy sitting on the top-right edge of the chat input, with a laptop. The SVG is 100x102 units
   at 0.58px per unit; the torso's bottom (y 86) rests on the input's top edge and his blocky legs dangle
   over the field, tapping up and down. */
.mp-root {
  position: absolute;
  right: 12px;
  bottom: calc(100% - 9px);
  z-index: 3;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  line-height: 0;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* The SVG's empty margins shouldn't swallow clicks meant for the input; only Patchy himself is poke-able. */
  pointer-events: none;
  /* idle: orange, the app's accent (Patchy was cyan until the theme went black, grey and orange) */
  --mp-accent: #cf8a5a;
  --mp-leg: 0.5s; /* half a cycle of the leg taps */
}

.mp-root svg > * { pointer-events: auto; }

/* The chat input area styles every <button> inside it (blue background, lift and shadow on hover/press).
   Patchy is a button in there but isn't one of those, so cancel all of it. */
.chat-input-area button.mp-root,
.chat-input-area button.mp-root:hover:not(:disabled),
.chat-input-area button.mp-root:active:not(:disabled) {
  background: transparent;
  box-shadow: none;
  transform: none;
  border: 0;
  border-radius: 0;
  padding: 0;
}

.mp-root:focus-visible {
  outline: 2px dashed var(--mp-accent);
  outline-offset: 2px;
}

.mp-root .mp-accent { fill: var(--mp-accent); transition: fill 0.3s ease; }
.mp-root .mp-stroke-accent { stroke: var(--mp-accent); transition: stroke 0.3s ease; }

/* Every expression is always drawn and faded in or out (see PatchyParts.tsx), so a change of look is a crossfade. */
.mp-fade { opacity: 0; transition: opacity 0.25s ease; }
.mp-fade.mp-on { opacity: 1; }

.mp-working { --mp-accent: #eab308; } /* the same yellow the full-size Patchy uses for "analyzing" */
.mp-done    { --mp-accent: #22c55e; }
.mp-laugh   { --mp-accent: #ec4899; }

/* ---- idle: blocky legs tapping up and down in turn, a head tilt, a pulsing antenna, a blink ---- */
.mp-leg { animation: mp-leg-tap var(--mp-leg) ease-in-out infinite alternate; }
.mp-leg-r { animation-delay: calc(var(--mp-leg) * -1); }
@keyframes mp-leg-tap {
  from { transform: translateY(0); }
  to { transform: translateY(-5px); }
}
.mp-working { --mp-leg: 0.28s; }
.mp-done, .mp-laugh { --mp-leg: 0.16s; }

/* The head. Two layers, so that no look change snaps it:
   - .mp-head sways forever (the original Patchy's head tilt). Its two extremes are --mp-lo and --mp-hi, registered properties, so each look can set
     how far it sways (idle the full tilt, working none) and the sway eases between amounts instead of one animation being swapped for another.
   - .mp-turn, inside it, holds the head's pose for the look (bowed over the laptop, tipped to one side, drooping asleep, turned to the input) and
     transitions between poses. */
@property --mp-lo { syntax: '<angle>'; inherits: true; initial-value: -7deg; }
@property --mp-hi { syntax: '<angle>'; inherits: true; initial-value: 5deg; }
@property --mp-wob { syntax: '<number>'; inherits: true; initial-value: 0; }
.mp-root { --mp-lo: -7deg; --mp-hi: 5deg; --mp-wob: 0; transition: --mp-lo 0.5s ease, --mp-hi 0.5s ease, --mp-wob 0.4s ease; }
.mp-head { transform-origin: 50px 54px; animation: mp-tilt 7s ease-in-out infinite; }
@keyframes mp-tilt {
  0%, 50%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(var(--mp-lo)); }
  75% { transform: rotate(var(--mp-hi)); }
}

.mp-antenna { animation: mp-pulse 2s ease-in-out infinite; }
@keyframes mp-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

.mp-eyes {
  transform-box: fill-box;
  transform-origin: center;
  animation: mp-blink 4.2s infinite;
}
@keyframes mp-blink {
  0%, 45%, 52%, 100% { transform: scaleY(1); }
  48% { transform: scaleY(0.08); }
}

/* Code lines and a blinking cursor on the laptop's screen */
.mp-line { transform-box: fill-box; transform-origin: left center; }
.mp-cursor { animation: mp-cursor 1s steps(1) infinite; }
@keyframes mp-cursor {
  0%, 49.99% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ---- working: looking down at the laptop (head bowed, eyes low), hands tapping, code building line by line ---- */
.mp-working { --mp-lo: 0deg; --mp-hi: 0deg; }
.mp-working .mp-turn { transform: rotate(4deg) translateY(1.5px); }
.mp-working .mp-eyes { translate: 0 3px; }

.mp-working .mp-hand-l { animation: mp-tap 0.28s ease-in-out infinite alternate; }
.mp-working .mp-hand-r { animation: mp-tap 0.28s ease-in-out 0.14s infinite alternate; }
@keyframes mp-tap {
  from { transform: translateY(0); }
  to { transform: translateY(-2px); }
}

.mp-working .mp-line { animation: mp-code 1.2s steps(6) infinite; }
.mp-working .mp-line-2 { animation-delay: 0.4s; }
.mp-working .mp-line-3 { animation-delay: 0.8s; }
@keyframes mp-code {
  0% { transform: scaleX(0.1); }
  100% { transform: scaleX(1); }
}

.mp-working .mp-antenna { animation-duration: 0.6s; }

/* ---- energy follows the user's emotional state (see MiniPatchy.tsx) ---- */
/* easing: a small lift has been shown, so gentler, not flat */
.mp-e-easing { --mp-leg: 1.1s; }
.mp-e-easing.mp-idle { --mp-accent: #c28c66; }
.mp-e-easing.mp-done .mp-bob { animation: mp-hop-small 0.5s ease-out 2; }
@keyframes mp-hop-small {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-2px); }
}
.mp-e-easing.mp-laugh .mp-bob { animation-duration: 0.5s; }

/* subdued: low or frustrated with no lift yet, so quiet and steady */
.mp-e-subdued.mp-idle { --mp-accent: #a8907c; }
.mp-e-subdued.mp-working { --mp-accent: #c4a94f; }
.mp-e-subdued.mp-done { --mp-accent: #6fb58a; }
.mp-e-subdued .mp-leg { animation: none; }
.mp-e-subdued .mp-antenna { animation-duration: 4s; }
.mp-e-subdued.mp-working .mp-antenna { animation-duration: 1.6s; }
/* Head tilted toward you, swaying a little: attentive and concerned */
.mp-e-subdued.mp-idle { --mp-lo: -2deg; --mp-hi: 2deg; }
.mp-e-subdued.mp-idle .mp-turn { transform: rotate(4deg); }
/* Wide open eyes, a touch larger: he is watching you, not drifting */
.mp-e-subdued.mp-idle .mp-eyes { scale: 1.12; }
.mp-e-subdued.mp-working .mp-hand-l,
.mp-e-subdued.mp-working .mp-hand-r { animation-duration: 0.5s; }
.mp-e-subdued.mp-working .mp-line { animation-duration: 2.2s; }
.mp-e-subdued.mp-done .mp-bob { animation: mp-nod 0.9s ease-in-out 1; }
.mp-soft .mp-bob { animation: mp-nod 1s ease-in-out 1; }
@keyframes mp-nod {
  0%, 100% { transform: translateY(0); }
  40% { transform: translateY(1.5px); }
}

/* ---- done: a check pops off the laptop and he hops ---- */
.mp-done .mp-bob { animation: mp-hop 0.4s ease-out 3; }
@keyframes mp-hop {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-5px); }
}
.mp-sent { animation: mp-send 1.3s ease-out forwards; transform-box: fill-box; transform-origin: center; }
@keyframes mp-send {
  0% { transform: translate(0, 0) scale(0.6); opacity: 0; }
  15% { opacity: 1; }
  100% { transform: translate(8px, -26px) scale(1); opacity: 0; }
}

/* ---- poked: giggle ---- */
.mp-laugh .mp-bob { animation: mp-giggle 0.3s ease-in-out infinite; }
@keyframes mp-giggle {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  25% { transform: translate(-1px, -2px) rotate(-3deg); }
  75% { transform: translate(1px, -2px) rotate(3deg); }
}
.mp-laugh::after {
  content: 'hehe!';
  position: absolute;
  right: 100%;
  top: 6px;
  margin-right: 1px;
  font: 700 9px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.4px;
  color: var(--mp-accent);
  white-space: nowrap;
  pointer-events: none;
}

/* ==========================================================================================================================================
   What he does while a turn runs, and the other moods (see patchyLook.ts for when each one applies). "Writing" is .mp-working, above.
   ========================================================================================================================================== */

.mp-thinking  { --mp-accent: #eab308; --mp-leg: 0.9s; }
.mp-searching { --mp-accent: #a855f7; --mp-leg: 0.7s; }
.mp-puzzled   { --mp-accent: #38c2de; --mp-leg: 0.7s; }
.mp-error     { --mp-accent: #ef4444; --mp-leg: 1.2s; }
.mp-drowsy    { --mp-accent: #7fb4c9; --mp-leg: 1.8s; }
.mp-asleep    { --mp-accent: #8aa0c8; }
.mp-asleep .mp-leg { animation: none; }

/* ---- thinking: a hand to his head bobbing, his eyes up and to the side, a thought forming ---- */
.mp-thinking { --mp-lo: -2deg; --mp-hi: 2deg; }
.mp-thinking .mp-turn { transform: rotate(-5deg); }
.mp-thinking .mp-eyes { translate: 1.5px -2px; }
/* He turns toward the side his eyes look to (the viewer's right): that ear foreshortens behind the face, the other swings into view and grows. */
.mp-thinking .mp-ear-r { transform: translateX(-0.6px) scaleX(0.72); }
.mp-thinking .mp-ear-l { transform: translateX(1.8px) scaleX(1.4); }
.mp-dot { opacity: 0.9; animation: mp-dot 1.4s ease-in-out infinite; }
.mp-dot-2 { animation-delay: 0.25s; }
.mp-dot-3 { animation-delay: 0.5s; }
@keyframes mp-dot {
  0%, 100% { opacity: 0.15; }
  50% { opacity: 1; }
}
.mp-thinking .mp-antenna { animation-duration: 0.9s; }

/* ---- searching: a magnifying glass over his eye, scanning slowly; his head holds still so the lens stays on the eye.
   The right arm is always in a .mp-scan group, which wobbles by --mp-wob (0 nearly always, 1 while searching) so the scan eases in and out. ---- */
.mp-searching { --mp-lo: 0deg; --mp-hi: 0deg; --mp-wob: 1; }
.mp-scan { transform-origin: 66px 45px; animation: mp-scan 2.6s ease-in-out infinite; }
@keyframes mp-scan {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  33% { transform: translate(calc(-2px * var(--mp-wob)), calc(-1px * var(--mp-wob))) rotate(calc(-3deg * var(--mp-wob))); }
  66% { transform: translate(calc(1px * var(--mp-wob)), calc(1px * var(--mp-wob))) rotate(calc(2deg * var(--mp-wob))); }
}

/* ---- puzzled: head tipped, one brow up, a question mark, a sweat drop ---- */
.mp-puzzled { --mp-lo: -2.5deg; --mp-hi: 2.5deg; }
.mp-puzzled .mp-turn { transform: rotate(-6.5deg); }
.mp-q { transform-box: fill-box; transform-origin: center; animation: mp-q 1.3s ease-in-out infinite; }
@keyframes mp-q {
  0%, 100% { transform: translateY(0) rotate(-6deg); }
  50% { transform: translateY(-2px) rotate(6deg); }
}
.mp-sweat { animation: mp-sweat 2.2s ease-in infinite; }
@keyframes mp-sweat {
  0% { transform: translateY(0); opacity: 0; }
  25% { opacity: 0.9; }
  80% { transform: translateY(9px); opacity: 0.8; }
  100% { transform: translateY(13px); opacity: 0; }
}
/* The budget's notice level: the same drop, but slow and rare, so it is a hint and not a nag */
.mp-b-notice:not(.mp-puzzled) .mp-sweat { animation-duration: 4.5s; animation-delay: 1s; }

/* ---- error: sorry and red, a short alarmed shake, a quick antenna ---- */
.mp-error { --mp-lo: 0deg; --mp-hi: 0deg; }
.mp-error .mp-turn { transform: rotate(-3deg) translateY(1px); }
.mp-error .mp-bob { animation: mp-alarm 0.5s ease-in-out 4; }
@keyframes mp-alarm {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  25% { transform: translate(-1px, 0) rotate(-1.5deg); }
  75% { transform: translate(1px, 0) rotate(1.5deg); }
}
.mp-error .mp-antenna { animation-duration: 0.5s; }
/* A low person is not shown an alarm: a slow nod, a soft rose, no shake */
.mp-e-subdued.mp-error { --mp-accent: #d98a8a; }
.mp-e-subdued.mp-error .mp-bob { animation: mp-nod 1.4s ease-in-out 1; }
.mp-e-subdued.mp-error .mp-antenna { animation-duration: 3s; }
.mp-e-subdued.mp-thinking { --mp-accent: #c4a94f; }
.mp-e-subdued.mp-searching { --mp-accent: #a58bd1; }
.mp-e-subdued.mp-puzzled { --mp-accent: #7f9cc9; }

/* ---- watching the input (you have clicked into it or typed): he turns his head toward it and looks down. It is a turn, simulated flat: the whole head bows a little, the
   face slides across the shell toward the box (the visor, eyes and mouth move more than the shell does, which is what reads as depth), the shell
   narrows slightly, the ear on the side he turns toward foreshortens behind the face while the other swings into view and grows, and his eyes drop. With text in the box (.mp-reading) he turns
   further and looks lower, as if reading it. Everything is a transition, so clicking in, typing the first letter and clearing the box all ease. ---- */
.mp-watching { --mp-lo: 0deg; --mp-hi: 0deg; }
.mp-turn, .mp-face, .mp-shell, .mp-ear { transition: transform 0.55s cubic-bezier(0.3, 0.7, 0.3, 1); }
.mp-eyes { transition: translate 0.4s cubic-bezier(0.3, 0.7, 0.3, 1), scale 0.4s ease; }
.mp-turn { transform-origin: 50px 54px; }
.mp-shell, .mp-ear, .mp-face { transform-box: fill-box; transform-origin: center; }
.mp-ear-l { transform-origin: right center; }
.mp-ear-r { transform-origin: left center; }

/* The small Patchy is drawn at 0.58 scale, so the turn has to be bold in the SVG's own units to read at all: these are about 2 to 3 real pixels. */
.mp-watching .mp-turn { transform: translate(-1px, 1.5px) rotate(-5deg); }
.mp-watching .mp-face { transform: translate(-3px, 1.5px) scaleX(0.93); }
.mp-watching .mp-shell { transform: scaleX(0.94); }
.mp-watching .mp-ear-r { transform: translateX(-1.8px) scaleX(1.5); }
.mp-watching .mp-ear-l { transform: translateX(1.2px) scaleX(0.5); }
.mp-watching .mp-eyes { translate: -1.5px 2px; }

.mp-watching.mp-reading .mp-turn { transform: translate(-1.5px, 3px) rotate(-8deg); }
.mp-watching.mp-reading .mp-face { transform: translate(-4px, 3px) scaleX(0.88); }
.mp-watching.mp-reading .mp-shell { transform: scaleX(0.92); }
.mp-watching.mp-reading .mp-ear-r { transform: translateX(-2.2px) scaleX(1.7); }
.mp-watching.mp-reading .mp-ear-l { transform: translateX(1.8px) scaleX(0.4); }
.mp-watching.mp-reading .mp-eyes { translate: -2px 2.5px; }

/* ---- drowsy: heavy lids (drawn in the head), a head drooping a little and swaying slowly ---- */
.mp-drowsy { --mp-lo: -1deg; --mp-hi: 1deg; }
.mp-drowsy .mp-turn { transform: rotate(5deg) translateY(1.5px); }
.mp-drowsy .mp-antenna { animation-duration: 4s; }

/* ---- asleep (chat is paused): eyes closed, head resting, slow breathing, z's drifting up ---- */
.mp-asleep { --mp-lo: 0deg; --mp-hi: 0deg; }
.mp-asleep .mp-turn { transform: rotate(9deg) translateY(2px); }
.mp-asleep .mp-bob { animation: mp-breathe 3.2s ease-in-out infinite; }
@keyframes mp-breathe {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(1px); }
}
.mp-asleep .mp-antenna { animation-duration: 5s; }
.mp-z { opacity: 0.85; animation: mp-zfloat 3s ease-in-out infinite; }
.mp-z-2 { animation-delay: 1s; }
.mp-z-3 { animation-delay: 2s; }
@keyframes mp-zfloat {
  0% { opacity: 0; transform: translate(0, 4px); }
  25% { opacity: 0.95; }
  100% { opacity: 0; transform: translate(4px, -8px); }
}

/* ---- the budget's throttled level: weary. Heavy lids (drawn in the head), slower legs and antenna, a drooping head when idle ---- */
.mp-b-throttled { --mp-leg: 1.6s; }
.mp-b-throttled .mp-antenna { animation-duration: 4s; }
.mp-b-throttled.mp-idle { --mp-lo: -1.5deg; --mp-hi: 1.5deg; }
.mp-b-throttled.mp-idle .mp-turn { transform: rotate(4.5deg) translateY(0.5px); }

/* ---- steered: a message was sent into the turn that is running; he nods "got it" ---- */
/* The nod uses the individual rotate and translate properties, which add to the head's pose (transform) instead of replacing it. */
.mp-steered .mp-turn { animation: mp-steer-nod 0.55s ease-in-out 2; }
@keyframes mp-steer-nod {
  0%, 100% { rotate: 0deg; translate: 0 0; }
  40% { rotate: 2deg; translate: 0 2.5px; }
  70% { rotate: -1deg; translate: 0 -0.5px; }
}
.mp-steered::after {
  content: 'got it';
  position: absolute;
  right: 100%;
  top: 6px;
  margin-right: 1px;
  font: 700 9px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.4px;
  color: var(--mp-accent);
  white-space: nowrap;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .mp-root *, .mp-root::after { animation: none !important; transition: none !important; }
}

/* The embedded widget (BTY) has its own mini Patchy in the parent page. */
.bty-embed-container .mp-root { display: none; }
/* The landing page's Patchy (PatchyAtLaptop.tsx). It reuses the chat input Patchy's classes (MiniPatchy.css) for his colours and his typing, and only places
   him and turns him. He is sized by --ps-h (the height of his drawing) and sits on the floor, which is the bottom edge of the panel he is in: the drawing's
   floor is at 94 of 96 units, so he stands a hair below the edge and nothing hangs over the panels beneath. */
.ps-root.mp-root {
  position: absolute;
  left: 50%;
  right: auto;
  bottom: calc(var(--ps-h) * -0.02);
  height: var(--ps-h);
  aspect-ratio: 112 / 96;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: 5;
  --mp-accent: var(--ps-accent, #f0883e);
}

/* His own orange is on his face, hands, chest and antenna, which sit on dark. The steam and the bits of code float against the page, so they are a lighter orange. */
/* The light on his antenna is the source of the glow around him: it is his own orange, glowing, and flickering on the same beat as the light behind him. */
.ps-root .mp-antenna {
  transform-box: fill-box;
  transform-origin: center;
  filter: drop-shadow(0 0 1.4px #f0883e) drop-shadow(0 0 3.6px rgba(240, 136, 62, 0.8));
  animation: ld-flame 3.7s linear infinite;
}
.ps-root .ps-steam { stroke: var(--ps-glint, #ffe3c2); }
.ps-root .ps-bits { fill: var(--ps-glint, #ffe3c2); }

.ps-root svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

/* Only his drawing is clickable, not the empty space around it. Clicking startles him: a quick hop, a squashed landing and a smaller bounce, pivoting on the floor. */
.ps-jump { pointer-events: auto; cursor: pointer; transform-box: fill-box; transform-origin: 50% 100%; }
.ps-startled { animation: ps-startle 0.75s ease-out; }
@keyframes ps-startle {
  0% { transform: translateY(0) scale(1, 1); }
  14% { transform: translateY(-11px) scale(0.96, 1.06); }
  36% { transform: translateY(0) scale(1.06, 0.92); }
  54% { transform: translateY(-4px) scale(0.99, 1.02); }
  74% { transform: translateY(0) scale(1.02, 0.97); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* Hunched over: everything above the hips leans toward the laptop (to his left, our left). */
.ps-upper { transform: rotate(-13deg); transform-origin: 58px 94px; }

/* The turn: the head bows over the screen and the face slides across the shell. His near ear is drawn on the side of the head (PatchyHead, focused), so
   the two ears that sit behind the shell are hidden. */
.ps-head { transform: rotate(-7deg); transform-origin: 58px 64px; }
.ps-root .mp-face { transform: translateX(-5px); }
.ps-root .mp-shell { transform: scaleX(0.9); }
.ps-root .mp-ear-r, .ps-root .mp-ear-l { opacity: 0; }

/* Startled (PatchyAtLaptop.tsx): once he has landed he turns to face us, down the barrel like the chat Patchy, and waves, easing out of the turn above and back into it after. */
.ps-upper, .ps-head { transition: transform 0.5s cubic-bezier(0.3, 0.7, 0.3, 1); }
.ps-root .mp-ear-r, .ps-root .mp-ear-l, .ps-ear-near { transition: opacity 0.35s ease, transform 0.55s cubic-bezier(0.3, 0.7, 0.3, 1); }
.ps-front .ps-upper { transform: rotate(-3deg); }
.ps-front .ps-head { transform: rotate(0deg); }
.ps-front .mp-face { transform: none; }
.ps-front .mp-shell { transform: none; }
.ps-front .mp-ear-r, .ps-front .mp-ear-l { opacity: 1; }
.ps-front .ps-ear-near { opacity: 0; }

/* The waving arm is hidden until then; the arm that reaches across to the keys lets go for the wave. The wave itself is PatchyRightArm's (its path is eased in script), so the arm is rubber, not jointed. */
.ps-wave-arm { opacity: 0; }
.ps-near-arm, .ps-near-hand { transition: opacity 0.25s ease; }
.ps-front .ps-wave-arm { opacity: 1; }
.ps-front .ps-near-arm, .ps-front .ps-near-hand { opacity: 0; }

/* Too busy to notice anyone: his eyes are flat dashes ("-_-") most of the time; every so often they turn into two little dots that sweep right to left, snap back and
   sweep again, three times, as if he had just read three lines of code, and then go back, with his mouth falling open a little ("oooh") while he reads. (Under "reduce motion" nothing animates and he keeps the dash face.) */
.ps-eyes-dash { animation: ps-dash 9s ease-in-out infinite; }
.ps-mouth-flat { animation: ps-dash 9s ease-in-out infinite; }
.ps-eyes-dots { opacity: 0; animation: ps-dots 9s ease-in-out infinite; }
@keyframes ps-dash { 0%, 42% { opacity: 1; } 47%, 90% { opacity: 0; } 95%, 100% { opacity: 1; } }
@keyframes ps-dots { 0%, 42% { opacity: 0; } 47%, 90% { opacity: 1; } 95%, 100% { opacity: 0; } }
.ps-dots-run { animation: ps-run 9s ease-in-out infinite; }
@keyframes ps-run {
  0%, 47% { transform: translateX(3.5px); }
  57% { transform: translateX(-3.5px); }
  58% { transform: translateX(3.5px); }
  68% { transform: translateX(-3.5px); }
  69% { transform: translateX(3.5px); }
  79%, 100% { transform: translateX(-3.5px); }
}

/* His feet tip a little now and then, like someone who is concentrating. */
.ps-foot { transform-box: fill-box; transform-origin: 50% 100%; animation: ps-toes 3.1s ease-in-out infinite; }
.ps-foot-far { animation-delay: -1.2s; }
.ps-foot-front { animation-delay: -2.2s; }
@keyframes ps-toes { 0%, 100% { transform: rotate(0deg); } 50% { transform: rotate(-9deg); } }

/* The laptop's light breathes a little. */
.ps-glow { animation: ps-breathe 4.2s ease-in-out infinite; }
@keyframes ps-breathe { 0%, 100% { opacity: 0.75; } 50% { opacity: 1; } }

/* Steam from the mug. */
.ps-steam { opacity: 0; animation: ps-steam 3.4s ease-in-out infinite; }
.ps-steam-2 { animation-delay: 1.5s; }
@keyframes ps-steam {
  0% { opacity: 0; transform: translateY(2px); }
  35% { opacity: 0.7; }
  100% { opacity: 0; transform: translateY(-4px); }
}

/* Bits of code float up off the laptop and fade, a few at a time. */
.ps-bit { opacity: 0; animation: ps-bit 3.6s ease-in infinite; }
.ps-bit-2 { animation-delay: 0.9s; animation-duration: 4.1s; }
.ps-bit-3 { animation-delay: 1.8s; animation-duration: 3.3s; }
.ps-bit-4 { animation-delay: 2.5s; animation-duration: 4.4s; }
@keyframes ps-bit {
  0% { opacity: 0; transform: translateY(2px); }
  15% { opacity: 0.85; }
  100% { opacity: 0; transform: translateY(-22px) translateX(-4px); }
}

@media (prefers-reduced-motion: reduce) {
  .ps-bit { animation: none; opacity: 0.5; }
  .ps-glow, .ps-steam { animation: none; }
  .ps-steam { opacity: 0.45; }
  .ps-root *, .ps-root { animation: none !important; }
}

/* A phone: smaller, and a little further in from the edge so his mug is not cut off. */
@media (max-width: 768px) {
  .ps-root.mp-root { --mp-leg: 1.6s; }
}
/* The app's loading spinner (components/Spinner.tsx): a ring with one bright arc. Colours come from the theme, so it works in light and dark. */
.app-spinner {
  display: inline-block;
  box-sizing: border-box;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 3px solid var(--spinner-track, rgba(100, 116, 139, 0.25));
  border-top-color: var(--spinner-color, var(--accent-primary, #2563eb));
  animation: app-spinner-turn 0.9s linear infinite;
}

@keyframes app-spinner-turn {
  to { transform: rotate(360deg); }
}

/* Someone who has asked their device for less motion gets a slow turn instead of a fast one: it still shows that something is happening. */
@media (prefers-reduced-motion: reduce) {
  .app-spinner { animation-duration: 3s; }
}
/* Diff card for edits Sonic proposes to the user's connected local folder (LocalEditCard.tsx).
   Always dark, like the code blocks and live-browser embed beside it, so it reads the same in
   both themes. */
.led-card {
  margin: 0.5rem 0;
  border: 1px solid color-mix(in srgb, var(--text-muted) 25%, transparent);
  border-radius: 10px;
  overflow: hidden;
  background: color-mix(in srgb, var(--card-bg) 96%, transparent);
  color: var(--text-main);
  font-size: 0.85rem;
}

.led-header {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid color-mix(in srgb, var(--text-muted) 15%, transparent);
}

.led-title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.led-stats {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.led-add { color: color-mix(in srgb, var(--accent-success) 78%, var(--text-main)); }
.led-del { color: color-mix(in srgb, var(--accent-danger) 78%, var(--text-main)); }

.led-summary {
  margin-top: 0.3rem;
  color: var(--text-soft);
}

.led-file {
  border-bottom: 1px solid color-mix(in srgb, var(--text-muted) 12%, transparent);
}

.led-file-header {
  display: flex;
  width: 100%;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  background: color-mix(in srgb, var(--chip-bg) 70%, transparent);
  border: 0;
  color: var(--text-main);
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  text-align: left;
  cursor: pointer;
}

.led-file-kind {
  flex: none;
  color: var(--text-muted);
}

.led-diff {
  margin: 0;
  padding: 0.4rem 0;
  max-height: 320px;
  overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.45;
}

.led-diff > div {
  padding: 0 0.75rem;
  white-space: pre;
}

.led-line-add { background: color-mix(in srgb, var(--accent-success) 14%, transparent); color: color-mix(in srgb, var(--accent-success) 78%, var(--text-main)); }
.led-line-del { background: color-mix(in srgb, var(--accent-danger) 15%, transparent); color: color-mix(in srgb, var(--accent-danger) 78%, var(--text-main)); }
.led-line-hunk { color: var(--accent-primary); }
.led-line-meta { color: var(--text-muted); }

.led-errors {
  padding: 0.5rem 0.75rem;
  background: color-mix(in srgb, var(--accent-danger) 12%, transparent);
  color: color-mix(in srgb, var(--accent-danger) 78%, var(--text-main));
}

.led-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.75rem;
}

.led-btn {
  padding: 0.4rem 0.9rem;
  border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--text-muted) 40%, transparent);
  background: transparent;
  color: var(--text-main);
  font: inherit;
  cursor: pointer;
}

.led-btn:disabled { opacity: 0.55; cursor: default; }

.led-btn-primary {
  background: var(--accent-primary);
  border-color: transparent;
  color: var(--on-accent);
}

.led-note { color: var(--text-muted); }
.led-ok { color: color-mix(in srgb, var(--accent-success) 78%, var(--text-main)); }
/* One-time consent dialog before connecting a local folder (LocalFolderConsent.tsx). Styled like
   the delete-conversation confirm in Chat.tsx so the two dialogs look related. */
.lfc-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(4px);
}

.lfc-dialog {
  width: 100%;
  max-width: 460px;
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
  padding: 1.5rem;
  border: 1px solid color-mix(in srgb, var(--text-muted) 20%, transparent);
  border-radius: 12px;
  background: var(--chip-bg);
  color: var(--text);
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5);
}

.lfc-title {
  margin: 0 0 0.5rem 0;
  font-size: 1.1rem;
  font-weight: 600;
}

.lfc-lead {
  margin: 0 0 0.75rem 0;
  font-size: 0.85rem;
  color: var(--text-soft);
}

.lfc-list {
  margin: 0 0 1.25rem 0;
  padding-left: 1.1rem;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-muted);
}

.lfc-list li + li {
  margin-top: 0.5rem;
}

.lfc-list strong {
  color: var(--text-main);
}

.lfc-list code {
  padding: 0.05em 0.3em;
  border-radius: 4px;
  background: color-mix(in srgb, var(--chip-bg) 70%, transparent);
  font-size: 0.95em;
}

.lfc-actions {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.lfc-btn {
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: transparent;
  color: var(--text-soft);
  font-size: 0.85rem;
  cursor: pointer;
}

.lfc-btn-primary {
  border-color: transparent;
  background: var(--accent-primary);
  color: var(--on-accent);
}
.conversations-panel-container {
  position: fixed;
  left: 0;
  top: 0;
  height: 100%;
  width: 350px;
  background: var(--bg-main);
  border-right: 1px solid var(--border-color);
  overflow-y: auto;
  z-index: 900;
  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
  animation: conversationsSlideInLeft 0.25s ease-out;
}

@keyframes conversationsSlideInLeft {
  from { transform: translateX(-100%); }
  to { transform: translateX(0); }
}

.conversations-panel-container.closing {
  animation: conversationsSlideOutLeft 0.25s ease-in forwards;
}

@keyframes conversationsSlideOutLeft {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

.conversations-panel {
  padding: 20px;
  background: var(--bg-main);
  height: 100%;
}

.conversations-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  
  margin-bottom: 16px;
}

.conversations-title {
  font-size: 1.2rem;
  font-weight: bold;
  margin: 0;
  color: var(--text-main);
}
.conversations-actions {
  display: flex;
  gap: 8px;
}
.conversations-exit-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--bg-main);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  padding: 6px 10px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 0.85rem;
  transition: all 0.2s ease;
}

.conversations-new-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--bg-main);
  border: 1px solid var(--border-color);
  color: var(--text-main);
  padding: 6px 10px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 0.85rem;
  transition: all 0.2s ease;
}

.conversations-new-btn:hover {
  box-shadow: var(--shadow-hover);
  transform: translateY(-1px);
}

.conversations-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.conversations-empty {
  color: var(--text-main);
  opacity: 0.6;
  font-size: 0.9rem;
  padding: 12px 4px;
}

.conversation-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: 1px solid transparent;
}

.conversation-row:hover {
  background: rgba(128, 128, 128, 0.08);
}

.conversation-row.active {
  border-color: var(--border-color);
  background: rgba(74, 111, 165, 0.1);
}

.conversation-row-main {
  min-width: 0;
  flex: 1;
}

.conversation-row-title {
  font-size: 0.9rem;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.conversation-row-time {
  font-size: 0.75rem;
  color: var(--text-main);
  opacity: 0.55;
  margin-top: 2px;
}

.conversation-delete-btn {
  background: transparent;
  border: none;
  color: var(--text-main);
  opacity: 0.5;
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  flex-shrink: 0;
  transition: all 0.15s ease;
}

.conversation-delete-btn:hover {
  opacity: 1;
  color: #ef4444;
  background: rgba(239, 68, 68, 0.1);
}
/* The full-size Patchy on the empty chat. It shares every expression with the small one (MiniPatchy.css); this only turns the small one's
   "sits on the input" layout into a standing figure that floats. */
.mp-hero {
  position: relative;
  right: auto;
  bottom: auto;
  display: inline-block;
  z-index: auto;
}

/* A backdrop glow in his current color */
.mp-hero .mph-glow { fill: var(--mp-accent); opacity: 0.12; transition: opacity 0.3s ease; }
.mp-asleep.mp-hero .mph-glow, .mp-drowsy.mp-hero .mph-glow { opacity: 0.06; }

/* He floats while he is up and about */
.mp-hero.mp-idle .mp-bob,
.mp-hero.mp-watching .mp-bob,
.mp-hero.mp-drowsy .mp-bob,
.mp-hero.mp-thinking .mp-bob,
.mp-hero.mp-searching .mp-bob,
.mp-hero.mp-puzzled .mp-bob,
.mp-hero.mp-working .mp-bob { animation: mph-float 4s cubic-bezier(0.45, 0, 0.55, 1) infinite; }
@keyframes mph-float {
  0%, 100% { transform: translateY(0) scale(1, 1); }
  50% { transform: translateY(-5px) scale(0.985, 1.015); }
  75% { transform: translateY(-1px) scale(1.01, 0.99); }
}
.mp-e-subdued.mp-hero .mp-bob { animation-duration: 7s; }

/* Feet dangle */
.mph-foot { animation: mph-dangle 4s ease-in-out infinite; }
.mph-foot-r { animation-delay: 0.3s; }
@keyframes mph-dangle {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(1.5px); }
}
.mp-asleep .mph-foot, .mp-e-subdued .mph-foot { animation: none; }

/* A calm signal off the antenna, only while he is standing by */
.mph-radar { opacity: 0; }
.mp-idle.mp-e-open .mph-radar-1 { animation: mph-radar 2.6s ease-out infinite; }
.mp-idle.mp-e-open .mph-radar-2 { animation: mph-radar 2.6s ease-out 1.3s infinite; }
@keyframes mph-radar {
  0% { r: 4px; opacity: 0.7; stroke-width: 1.5px; }
  100% { r: 16px; opacity: 0; stroke-width: 0.5px; }
}

/* The little speech labels (hehe! / got it) are sized for the small one; here they sit beside his head. */
.mp-hero.mp-laugh::after, .mp-hero.mp-steered::after { font-size: 12px; top: 18px; margin-right: -14px; }
.option-wheel {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  cursor: grab;
  outline: none;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.option-wheel--dragging {
  cursor: grabbing;
}

.option-wheel__item {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  gap: 0.55em;
  padding-left: var(--ow-inset, 0px);
  font-size: var(--ow-font-size, 1rem);
  color: var(--ow-text-color, #a6a6a6);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  will-change: transform, opacity, filter;
  transition: color 0.15s ease;
}

.option-wheel--right .option-wheel__item {
  flex-direction: row-reverse;
  padding-left: 0;
  padding-right: var(--ow-inset, 0px);
  text-align: right;
}

.option-wheel__item--selected {
  color: var(--ow-active-color, #cfd2dd);
  font-weight: 600;
}

.option-wheel__item-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 1em;
  height: 1em;
}

.option-wheel__item-icon svg {
  width: 1em;
  height: 1em;
  stroke: currentColor;
}

.option-wheel__item-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.option-wheel--column {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  cursor: default;
  height: auto;
}

.option-wheel--column .option-wheel__item {
  position: static;
  flex: none;
  padding: 0.55em 0.75em;
  border-radius: 8px;
  opacity: 1;
  filter: none;
  transform: none;
  will-change: auto;
}

.option-wheel--column .option-wheel__item:hover,
.option-wheel--column .option-wheel__item:focus-visible {
  background: color-mix(in srgb, var(--ow-active-color, #ffffff) 9%, transparent);
  color: var(--ow-active-color, #ffffff);
  outline: none;
}

.option-wheel--column .option-wheel__item--selected {
  background: color-mix(in srgb, var(--ow-active-color, #ffffff) 5%, transparent);
}

.option-wheel--column .option-wheel__item--disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}
.meeting-control {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  position: relative;
}

.meeting-control-msg {
  color: var(--text-muted);
  font-size: 0.8rem;
  max-width: 260px;
  line-height: 1.3;
}

/* The top bar's .topbar-btn is a fixed 34px icon square and loads after this file, so these are one class more specific: a button with words in it has to be allowed to be as wide as them. */
.topbar-btn.meeting-btn {
  width: auto;
  min-width: 34px;
  flex: 0 0 auto;
  padding: 0 0.75rem;
  border: 1px solid var(--line-strong);
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.topbar-btn.meeting-btn.meeting-btn-now,
.theme-shadow .topbar-btn.meeting-btn.meeting-btn-now {
  background-color: var(--accent-primary);
  color: var(--on-accent);
  border-color: var(--accent-primary);
}

.topbar-btn.meeting-btn.meeting-btn-active {
  border-color: var(--accent-primary);
}

.topbar-btn.meeting-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.meeting-btn-short {
  display: none;
}

.meeting-menu-wrap {
  position: relative;
}

.meeting-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 30;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  background-color: var(--card-bg, var(--input-bg));
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  box-shadow: var(--shadow);
  padding: 4px;
}

.meeting-menu-item {
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  padding: 0.5rem 0.7rem;
  border-radius: 6px;
  font-size: 0.85rem;
  cursor: pointer;
}

.meeting-menu-item:hover {
  background-color: color-mix(in srgb, var(--text-muted) 14%, transparent);
}

.meeting-menu-item-now {
  font-weight: 700;
}

@media (max-width: 640px) {
  .meeting-control-msg {
    display: none;
  }

  .meeting-btn-long {
    display: none;
  }

  .meeting-btn-short {
    display: inline;
  }

  .topbar-btn.meeting-btn {
    padding: 0 0.55rem;
    font-size: 0.75rem;
  }

  .meeting-menu {
    right: -40px;
    min-width: 200px;
  }
}
/* The usage budget status line above the chat box (components/BudgetBanner.tsx). Light colours by default; .budget-dark follows the
   app's own dark theme. */
.budget-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0 0 0.5rem 0;
  padding: 0.4rem 0.75rem;
  border-radius: 8px;
  border: 1px solid transparent;
  font-size: 0.8rem;
  line-height: 1.35;
}

.budget-banner-text {
  flex: 1 1 auto;
}

.budget-notice {
  background: rgba(245, 158, 11, 0.12);
  border-color: rgba(245, 158, 11, 0.45);
  color: #b45309;
}

.budget-throttled {
  background: rgba(249, 115, 22, 0.13);
  border-color: rgba(249, 115, 22, 0.5);
  color: #c2410c;
}

.budget-blocked {
  background: rgba(239, 68, 68, 0.13);
  border-color: rgba(239, 68, 68, 0.5);
  color: #b91c1c;
}

/* The app's own dark theme ("shadow"), not the operating system's setting. */
.budget-dark.budget-notice { color: #fbbf24; }
.budget-dark.budget-throttled { color: #fb923c; }
.budget-dark.budget-blocked { color: #f87171; }

/* The admin's "Extend by 25%" button, shown only on a blocked banner (components/BudgetBanner.tsx). */
.budget-extend {
  flex: 0 0 auto;
  padding: 0.15rem 0.7rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  font-size: 0.74rem;
  font-weight: 600;
  cursor: pointer;
}
.budget-extend:hover:not(:disabled) { background: rgba(239, 68, 68, 0.12); }
.budget-extend:disabled { opacity: 0.6; cursor: default; }
.budget-extend-error { flex: 0 0 auto; font-size: 0.72rem; font-weight: 600; }
/* The usage ring beside the "..." button (components/UsageRing.tsx). */
.usage-ring {
  /* The colour while usage is low, before it reaches the first threshold (the amber notice level). A blue that reads on the light page and on the dark one. */
  --usage-ok: #2f7de1;
  position: relative;
  flex: 0 0 auto;
  align-self: center; /* the buttons beside it are taller: keep it on their middle line */
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: default;
  outline: none;
}

.theme-shadow .usage-ring {
  --usage-ok: #5aa2f5;
}

.usage-ring-track {
  stroke: color-mix(in srgb, var(--text-muted) 30%, transparent);
}

/* It fills smoothly when usage grows. */
.usage-ring-fill {
  transition: stroke-dashoffset 0.6s ease, stroke 0.3s ease;
}

.usage-ring:focus-visible .usage-ring-track {
  stroke: color-mix(in srgb, var(--text-muted) 60%, transparent);
}

/* The words, shown above the ring on hover, keyboard focus or a tap. Anchored to the ring's right edge so it grows leftward, away from the
   screen's edge, which the icon row sits against on a phone. */
.usage-ring-tip {
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  padding: 0.3rem 0.6rem;
  border-radius: 8px;
  background: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--border-color);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.15s ease, transform 0.15s ease;
  z-index: 20;
}

.usage-ring:hover .usage-ring-tip,
.usage-ring:focus-visible .usage-ring-tip,
.usage-ring-tapped .usage-ring-tip {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .usage-ring-fill, .usage-ring-tip { transition: none; }
}
/* The execution trace panel (components/TracePanel.tsx): a blade on a wide screen, a bottom sheet on a phone. Theme variables, so it follows light and dark. */

.trace-blade {
  flex: 0 0 auto;
  width: 340px;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-alt);
  border-left: 1px solid var(--border-color);
  color: var(--text-main);
}
.theme-shadow .trace-blade { background: var(--panel-bg); }
.theme-shadow .trace-blade { border-left-color: var(--border-color); } /* and on the trace blade */

.trace-sheet-backdrop { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.45); z-index: 999; }
.trace-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 75vh;
  max-height: 75dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg-main);
  color: var(--text-main);
  border-top: 1px solid var(--border-color);
  border-radius: 18px 18px 0 0;
  z-index: 1000;
}
.theme-shadow .trace-sheet { background: var(--panel-bg); }
.trace-sheet-grip { flex: 0 0 auto; width: 36px; height: 4px; border-radius: 2px; background: var(--border-color); margin: 8px auto 0; }

.trace-panel-head { flex: 0 0 auto; display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 12px 14px 10px; border-bottom: 1px solid var(--border-color); }
.trace-panel-title { margin: 0; font-size: 0.92rem; font-weight: 700; }
.trace-panel-sub { margin-top: 2px; font-size: 0.76rem; color: var(--text-muted); }
.trace-panel-close { flex: 0 0 auto; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border: 0; border-radius: 8px; background: none; color: var(--text-muted); cursor: pointer; }
.trace-panel-close:hover { background: var(--bg-surface-hover); color: var(--text-main); }
.theme-shadow .trace-panel-close:hover { background: rgba(255, 255, 255, 0.08); }

.trace-panel-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px 16px 18px; display: flex; flex-direction: column; gap: 10px; }
.trace-status { font-family: monospace; font-size: 0.78rem; color: var(--text-muted); }
.trace-empty { font-size: 0.85rem; color: var(--text-muted); line-height: 1.5; }

/* ---- the path: steps as nodes joined by a line, flat (no cards, no shadows) ---- */
.trace-path { list-style: none; margin: 4px 0 0; padding: 0; }
.trace-node { position: relative; padding: 0 0 18px 32px; min-height: 22px; }
.trace-node-last { padding-bottom: 0; }

/* The node: a filled dot with a check once it is done; a ring with a pulsing core while it is running. */
.trace-node-dot {
  position: absolute;
  left: 0;
  top: 0;
  width: 20px;
  height: 20px;
  box-sizing: border-box;
  border-radius: 50%;
  border: 2px solid var(--accent-primary);
  background: var(--bg-main);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1;
}
.trace-node-done .trace-node-dot { background: var(--accent-primary); }
.trace-node-core { width: 8px; height: 8px; border-radius: 50%; background: var(--accent-primary); animation: trace-pulse 1.2s ease-in-out infinite; }
.trace-node-active .trace-node-dot::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  border: 2px solid var(--accent-primary);
  opacity: 0;
  animation: trace-ring 1.8s ease-out infinite;
}

/* The line to the next node: solid in the accent once the step is done (the way already travelled). */
.trace-node::before {
  content: '';
  position: absolute;
  left: 9px;
  top: 22px;
  bottom: 0;
  width: 2px;
  background: var(--accent-primary);
}
.trace-node-last::before { display: none; }
/* While a request runs, a dashed stub flows on from the last node, toward whatever comes next. */
.trace-node-running::after {
  content: '';
  position: absolute;
  left: 9px;
  top: 24px;
  height: 22px;
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--accent-primary) 0 4px, transparent 4px 8px);
  background-size: 2px 8px;
  animation: trace-flow 0.7s linear infinite;
  opacity: 0.7;
}
.trace-node-running { padding-bottom: 46px; }

.trace-node-text { min-width: 0; }
.trace-node-title { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 20px; font-size: 0.86rem; font-weight: 600; line-height: 1.3; }
.trace-node-active .trace-node-title { color: var(--accent-primary); }
.trace-node-detail { margin-top: 2px; font-size: 0.78rem; color: var(--text-muted); overflow-wrap: anywhere; }
.trace-batch { font-size: 0.66rem; font-weight: 600; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border-color); color: var(--accent-primary); }

/* The dark theme keeps the path to greys and black: a finished step is a grey dot on a grey line, and the one thing in the accent is the step that is
   running right now (its ring and its pulse). Nothing else on the blade is coloured. */
.theme-shadow .trace-node-dot { border-color: #3a3a40; background: #0e0e10; color: #cfcfd4; }
.theme-shadow .trace-node-done .trace-node-dot { background: #2c2c31; border-color: #3a3a40; }
.theme-shadow .trace-node::before { background: #2c2c31; }
.theme-shadow .trace-node-active .trace-node-dot { border-color: var(--accent-primary); }
.theme-shadow .trace-node-running::after {
  background: repeating-linear-gradient(to bottom, #4a4a52 0 4px, transparent 4px 8px);
  background-size: 2px 8px;
}
.theme-shadow .trace-node-active .trace-node-title { color: var(--text-main); }
.theme-shadow .trace-node-done .trace-node-title { font-weight: 500; color: #c4c4ca; }
.theme-shadow .trace-batch { color: var(--text-muted); }

@keyframes trace-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(0.8); }
}
@keyframes trace-ring {
  0% { opacity: 0.7; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.7); }
}
@keyframes trace-flow {
  from { background-position-y: 0; }
  to { background-position-y: 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .trace-node-core, .trace-node-active .trace-node-dot::after, .trace-node-running::after { animation: none; }
}
/* How Sonic's replies are set: lists, bold, headings, quotes, tables, rules and inline code.

   Until now only paragraphs were styled. A global reset (`* { margin: 0; padding: 0 }`) removes the browser's list indentation, so bullets sat on the
   text edge and a nested list lined up with its parent, and everything else was the browser default: a heavy flat heading, a hard-coded dark chip behind
   inline code, no table styling. This gives replies one look, built from the theme tokens, so it follows light and dark:

   - bullets are small accent diamonds (hollow one level down), numbers are small accent monospace figures (01, 02, 03);
   - bold carries a highlighter-pen swipe in the accent colour, not just weight;
   - h3 is a small uppercase accent label (like the AI/USER labels), h1 and h2 are plain bold with a hairline;
   - a quote has an accent rule, a horizontal rule starts with a short accent stub, a table is hairlines and small header labels;
   - inline code is a chip in the accent colour.

   Scoped to the app shell, so the embedded widget (which has none) keeps the look it has. */

/* Outside the app shell (the embedded widget) inline code keeps the look it always had: the chip that used to be an inline style on the element. */
.reply-code {
  background: rgba(51, 65, 85, 0.6);
  padding: 0.1em 0.35em;
  border-radius: 4px;
  font-size: 0.9em;
}

.app-shell .message-bubble.ai .message-text { line-height: 1.62; }
.app-shell .message-bubble.ai .message-text > :first-child { margin-top: 0; }
.app-shell .message-bubble.ai .message-text > :last-child { margin-bottom: 0; }
.app-shell .message-bubble.ai .message-text p { margin: 0.55rem 0; }

/* ---- lists ---- */
.app-shell .message-bubble.ai .message-text ul, .app-shell .message-bubble.ai .message-text ol { list-style: none; margin: 0.5rem 0; padding: 0; }
.app-shell .message-bubble.ai .message-text li { position: relative; margin: 0.34rem 0; padding-left: 1.45rem; }
.app-shell .message-bubble.ai .message-text li > p { margin: 0; }
.app-shell .message-bubble.ai .message-text li > p + p { margin-top: 0.35rem; }
.app-shell .message-bubble.ai .message-text li > ul, .app-shell .message-bubble.ai .message-text li > ol { margin: 0.3rem 0 0.1rem; }

.app-shell .message-bubble.ai .message-text ul > li::before {
  content: '';
  position: absolute;
  left: 0.3rem;
  top: 0.64em;
  width: 0.36rem;
  height: 0.36rem;
  background: var(--accent-primary);
  transform: rotate(45deg);
}
.app-shell .message-bubble.ai .message-text ul ul > li::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--accent-primary); }
.app-shell .message-bubble.ai .message-text ul ul ul > li::before { width: 0.3rem; height: 0.3rem; background: var(--text-muted); box-shadow: none; transform: none; border-radius: 50%; }

.app-shell .message-bubble.ai .message-text ol { counter-reset: reply-item; }
.app-shell .message-bubble.ai .message-text ol > li { counter-increment: reply-item; padding-left: 1.95rem; }
.app-shell .message-bubble.ai .message-text ol > li::before {
  content: counter(reply-item, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.2em;
  font-family: ui-monospace, 'Cascadia Code', 'Segoe UI Mono', Consolas, monospace;
  font-size: 0.74em;
  font-weight: 650;
  letter-spacing: 0.02em;
  color: var(--accent-primary);
}

/* a task list ("- [ ] item") has its own checkbox, so it gets no marker */
.app-shell .message-bubble.ai .message-text li.task-list-item { padding-left: 0; }
.app-shell .message-bubble.ai .message-text li.task-list-item::before { display: none; }
.app-shell .message-bubble.ai .message-text li.task-list-item input { margin-right: 0.5rem; accent-color: var(--accent-primary); }

/* ---- emphasis ---- */
.app-shell .message-bubble.ai .message-text strong {
  font-weight: 650;
  color: var(--text-main);
  background-image: linear-gradient(transparent 62%, color-mix(in srgb, var(--accent-primary) 24%, transparent) 62%);
  padding: 0 0.08em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.app-shell .message-bubble.ai .message-text em { font-style: italic; }

/* ---- inline code ---- */
.app-shell .message-bubble.ai .message-text .reply-code {
  font-family: ui-monospace, 'Cascadia Code', 'Segoe UI Mono', Consolas, monospace;
  font-size: 0.86em;
  padding: 0.12em 0.42em;
  border-radius: 5px;
  background: var(--chip-bg);
  border: 1px solid var(--line);
  color: var(--accent-primary);
  overflow-wrap: anywhere;
}

/* ---- headings ---- */
.app-shell .message-bubble.ai .message-text h1, .app-shell .message-bubble.ai .message-text h2 {
  margin: 1.2rem 0 0.45rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--line);
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text-main);
}
.app-shell .message-bubble.ai .message-text h3 {
  margin: 1.05rem 0 0.3rem;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-primary);
}
.app-shell .message-bubble.ai .message-text h4, .app-shell .message-bubble.ai .message-text h5, .app-shell .message-bubble.ai .message-text h6 { margin: 0.85rem 0 0.25rem; font-size: 0.92rem; font-weight: 650; color: var(--text-main); }

/* ---- quote, rule, table ---- */
.app-shell .message-bubble.ai .message-text blockquote {
  margin: 0.75rem 0;
  padding: 0.1rem 0 0.1rem 0.95rem;
  border-left: 3px solid var(--accent-primary);
  color: var(--text-soft);
}
.app-shell .message-bubble.ai .message-text blockquote p { margin: 0.3rem 0; }

.app-shell .message-bubble.ai .message-text hr {
  height: 1px;
  margin: 1.1rem 0;
  border: 0;
  background: linear-gradient(90deg, var(--accent-primary) 0, var(--accent-primary) 2rem, var(--line) 2rem);
}

.app-shell .message-bubble.ai .message-text table {
  display: block;
  max-width: 100%;
  margin: 0.75rem 0;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: 0.92em;
}
.app-shell .message-bubble.ai .message-text th, .app-shell .message-bubble.ai .message-text td { padding: 0.42rem 0.8rem; text-align: left; border-bottom: 1px solid var(--line); }
.app-shell .message-bubble.ai .message-text th {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
  border-bottom-color: var(--line-strong);
  white-space: nowrap;
}
.app-shell .message-bubble.ai .message-text tbody tr:last-child td { border-bottom: 0; }
/* The screen shown in place of the page until the person is fully signed in (components/AuthLoadingScreen.tsx). It takes the app's own theme
   variables, so it matches light and dark ("shadow") without a rule of its own for either. */
.auth-loading {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 60vh;
  padding: 2rem 16px;
  text-align: center;
  color: var(--text-main);
}

.auth-loading-title {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 600;
}

.auth-loading-detail {
  margin: 0;
  max-width: 28rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--text-muted);
}

.auth-loading-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
}

.auth-loading-btn {
  padding: 0.5rem 1.1rem;
  min-height: 44px; /* a comfortable tap target on a phone */
  border-radius: 8px;
  border: 1px solid var(--accent-primary);
  background: var(--accent-primary);
  color: #ffffff;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.auth-loading-btn-quiet {
  background: transparent;
  color: inherit;
}
.help-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 24px 28px;
  background: var(--bg-main);
  transition: all 0.2s ease;
  z-index: 952;
}

.help-panel .help-title {
  font-size: 1.4rem;
  font-weight: bold;
  margin-bottom: 5px;
}

.help-panel .help-subtitle {
  font-size: 0.9rem;
  color: var(--text-main);
  margin-bottom: 0;
  max-width: 720px;
}

.help-panel-header {
  padding-right: 32px; /* keep the subtitle clear of the close button */
  margin-bottom: 18px;
  flex-shrink: 0;
}

.help-panel-body {
  display: flex;
  gap: 24px;
  flex: 1;
  min-height: 0;
}

.help-nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 260px;
  flex-shrink: 0;
  overflow-y: auto;
  padding-right: 8px;
  border-right: 1px solid var(--border-color);
}

.help-nav-item {
  text-align: left;
  background: transparent;
  border: none;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 0.9rem;
  color: var(--text-main);
  cursor: pointer;
  transition: all 0.15s ease;
}

.help-nav-item:hover {
  background: var(--border-color);
}

.help-nav-item.active {
  background: var(--accent-soft);
  color: var(--accent-primary);
  font-weight: 600;
}

.help-nav-group {
  margin: 12px 0 2px;
  padding: 0 12px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.help-nav-group:first-child {
  margin-top: 0;
}

.help-nav-more {
  margin-top: 12px;
  color: var(--text-muted);
}

/* A button inside the words that takes you to a page ("Open Tidy up"). */
.help-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--accent-primary);
  text-decoration: underline;
  cursor: pointer;
}

.theme-shadow .help-link {
  color: var(--text-main);
}

.help-link:focus-visible,
.help-nav-item:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

.help-content {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
  padding: 4px 8px 4px 4px;
}

.help-content-title {
  margin-top: 0;
  margin-bottom: 12px;
  font-size: 1.1rem;
  color: var(--text-main);
}

.help-content p {
  margin: 0 0 12px;
  line-height: 1.5;
}

.help-content h4 {
  margin: 18px 0 6px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-primary);
}

.help-content h4:first-child {
  margin-top: 0;
}

.help-content ul {
  margin: 0 0 12px;
  padding-left: 20px;
}

.help-content li {
  margin-bottom: 6px;
  font-size: 0.95rem;
  line-height: 1.4;
}

.help-content .help-code {
  background: var(--bg-main);
  border: 1px solid var(--border-color);
  padding: 8px 12px;
  border-radius: 8px;
  font-family: monospace;
  font-size: 0.9rem;
  margin: 0 0 12px;
}

.help-panel-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 950;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: fadeInBackdrop 0.2s ease-out;
}

.help-panel-backdrop.closing {
  animation: fadeOutBackdrop 0.2s ease-in forwards;
}

@keyframes fadeInBackdrop {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes fadeOutBackdrop {
  from { opacity: 1; }
  to { opacity: 0; }
}

.help-panel-container {
  position: relative;
  width: min(94vw, 1400px);
  height: min(85vh, 820px);
  background: var(--bg-main);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  overflow: hidden;
  z-index: 952;
  box-shadow: var(--float-shadow);
  animation: popInHelp 0.2s ease-out;
}

.help-panel-container.closing {
  animation: popOutHelp 0.2s ease-in forwards;
}

@keyframes popInHelp {
  from { opacity: 0; transform: scale(0.96) translateY(8px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes popOutHelp {
  from { opacity: 1; transform: scale(1) translateY(0); }
  to { opacity: 0; transform: scale(0.96) translateY(8px); }
}

.help-panel-close-btn {
  position: absolute;
  top: 14px;
  right: 16px;
  background: transparent;
  border: none;
  color: var(--text-main);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 8px;
  z-index: 1;
}

.help-panel-close-btn:hover {
  background: var(--border-color);
}

@media (max-width: 768px) {
  .help-panel-container {
    width: 96vw;
    height: 92vh;
  }

  .help-panel {
    padding: 18px 16px;
  }

  .help-panel-body {
    flex-direction: column;
    gap: 12px;
  }

  .help-nav {
    flex-direction: row;
    flex-wrap: nowrap;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    border-right: none;
    border-bottom: 1px solid var(--border-color);
    padding-right: 0;
    padding-bottom: 8px;
  }

  .help-nav-item {
    flex-shrink: 0;
    white-space: nowrap;
  }

  /* On a phone the list is one scrolling row, so the group headings stay out of the way. */
  .help-nav-group {
    display: none;
  }

  .help-nav-more {
    margin-top: 0;
  }
}
/* The app shell (components/Layout.tsx): the rail on the left, a thin top bar, and the page filling the rest. It uses the theme variables from
   index.css, so it follows light and dark ("shadow") without rules of its own for either, except the rail's tint in dark. */

.portal-container.app-shell {
  flex-direction: row;
  width: 100%;
  height: 100vh;
  height: 100dvh; /* a phone's address bar changes 100vh; dvh follows what is actually visible */
  min-height: 0;
  overflow: hidden;
}

.app-main {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-main);
}

.app-content {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* ---------- the rail ---------- */

.app-rail {
  --rail-bg: var(--bg-alt);
  flex: 0 0 auto;
  width: 252px;
  height: 100%;
  min-height: 0;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 10px;
  background: var(--rail-bg);
  border-right: 1px solid var(--border-color);
  color: var(--text-main);
  position: relative;
  z-index: 20;
  transition: width 0.18s ease;
}

.theme-shadow .app-rail { --rail-bg: var(--panel-bg); }
/* .theme-shadow .app-rail { border-right-color: var(--edge); } an orange edge on the rail */
.app-rail-compact { width: 64px; align-items: center; padding: 12px 8px; }

.app-rail button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  margin: 0;
  cursor: pointer;
  text-align: left;
}

.rail-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 2px 2px 10px; width: 100%; box-sizing: border-box; }
.app-rail-compact .rail-head { justify-content: center; padding-bottom: 4px; }

.app-rail .rail-brand { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 2px; border-radius: 8px; }
.rail-wordmark { font-weight: 700; font-size: 0.98rem; letter-spacing: 0.2px; color: var(--accent-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.theme-shadow .rail-wordmark { color: var(--text-main); }

.app-rail .rail-icon-btn { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 8px; color: var(--text-muted); flex: 0 0 auto; }
.app-rail .rail-icon-btn:hover { background: var(--bg-surface-hover); color: var(--text-main); }
.theme-shadow .app-rail .rail-icon-btn:hover { background: rgba(255, 255, 255, 0.08); }

.app-rail .rail-new {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  margin: 2px 0 6px;
  border-radius: 10px;
  border: 1px solid var(--border-color);
  background: var(--bg-main);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--accent-primary);
}
.app-rail .rail-new:hover { background: var(--bg-surface-hover); }
.theme-shadow .app-rail .rail-new { color: var(--text-main); background: rgba(255, 255, 255, 0.04); }
.app-rail-compact .rail-new { width: 40px; height: 40px; justify-content: center; padding: 0; }

.rail-nav { display: flex; flex-direction: column; gap: 2px; width: 100%; }

.app-rail .rail-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 0.9rem;
  color: var(--text-main);
  border: 1px solid transparent;
}
.app-rail .rail-item:hover { background: var(--bg-surface-hover); }
.theme-shadow .app-rail .rail-item:hover { background: rgba(255, 255, 255, 0.06); }
.app-rail .rail-item.active { background: var(--bg-main); border-color: var(--border-color); font-weight: 600; }
.theme-shadow .app-rail .rail-item.active { background: rgba(255, 255, 255, 0.08); }
.app-rail-compact .rail-item { width: 40px; height: 40px; justify-content: center; padding: 0; }

.rail-recent { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; margin-top: 10px; width: 100%; }
.rail-section { font-size: 0.74rem; color: var(--text-muted); padding: 0 10px 4px; }
.rail-recent-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.rail-empty { font-size: 0.82rem; color: var(--text-muted); padding: 6px 10px; }
.rail-spacer { flex: 1 1 auto; }

.rail-convo { display: flex; align-items: center; border-radius: 8px; border: 1px solid transparent; }
.rail-convo:hover { background: var(--bg-surface-hover); }
.theme-shadow .rail-convo:hover { background: rgba(255, 255, 255, 0.06); }
.rail-convo.active { background: var(--bg-main); border-color: var(--border-color); }
.theme-shadow .rail-convo.active { background: rgba(255, 255, 255, 0.08); }
.app-rail .rail-convo-main { flex: 1 1 auto; min-width: 0; padding: 7px 10px; font-size: 0.86rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail-convo.active .rail-convo-main { font-weight: 600; }
.app-rail .rail-convo-delete { flex: 0 0 auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 6px; color: var(--text-muted); opacity: 0; }
.rail-convo:hover .rail-convo-delete, .rail-convo:focus-within .rail-convo-delete { opacity: 1; }
.app-rail .rail-convo-delete:hover { color: var(--accent-danger); }
@media (hover: none) { .app-rail .rail-convo-delete { opacity: 0.55; } }

/* ---------- the person's chip and menu ---------- */

.user-menu { position: relative; width: 100%; margin-top: 8px; }
.app-rail-compact .user-menu { width: auto; }

.app-rail .user-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
  padding: 6px;
  border-radius: 10px;
  border: 1px solid var(--border-color);
  background: var(--bg-main);
}
.app-rail .user-chip:hover { background: var(--bg-surface-hover); }
.theme-shadow .app-rail .user-chip { background: rgba(255, 255, 255, 0.04); }
.app-rail-compact .user-chip { width: auto; padding: 4px; border-radius: 50%; }

.user-avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--accent-primary); color: #fff; font-size: 0.72rem; font-weight: 700; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.theme-shadow .user-avatar { background: var(--accent-primary); }
.user-chip-name { flex: 1 1 auto; min-width: 0; font-size: 0.88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-chip-caret { color: var(--text-muted); flex: 0 0 auto; }

.user-menu-popover {
  position: absolute;
  left: 0;
  bottom: calc(100% + 8px);
  min-width: 100%;
  width: max-content;
  max-width: 280px;
  box-sizing: border-box;
  padding: 6px;
  background: var(--bg-main);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.18);
  z-index: 40;
}
.theme-shadow .user-menu-popover { background: var(--popover-bg); }
.app-rail-compact .user-menu-popover { min-width: 220px; }
.user-menu-who { padding: 8px 10px 8px; border-bottom: 1px solid var(--border-color); margin-bottom: 4px; }
.user-menu-name { font-weight: 600; font-size: 0.9rem; }
.user-menu-email { font-size: 0.78rem; color: var(--text-muted); overflow-wrap: anywhere; }
.app-rail .user-menu-item { display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 8px; font-size: 0.88rem; }
.app-rail .user-menu-item:hover { background: var(--bg-surface-hover); }
.theme-shadow .app-rail .user-menu-item:hover { background: rgba(255, 255, 255, 0.08); }
.app-rail .user-menu-danger { color: var(--accent-danger); }
.user-menu-divider { height: 1px; background: var(--border-color); margin: 4px 0; }

/* ---------- the top bar ---------- */

.app-topbar {
  flex: 0 0 auto;
  height: 44px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  background: var(--bg-main);
  border-bottom: 1px solid var(--border-color);
}
.topbar-title { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 0.95rem; font-weight: 600; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-sub { flex: 0 0 auto; font-size: 0.78rem; color: var(--text-muted); white-space: nowrap; }
.topbar-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.topbar-menu, .topbar-btn { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 8px; border: 0; background: none; color: var(--accent-primary); cursor: pointer; }
.theme-shadow .topbar-menu, .theme-shadow .topbar-btn { color: var(--text-main); }
.topbar-menu:hover, .topbar-btn:hover { background: var(--bg-surface-hover); }
.topbar-btn { position: relative; }
/* A pulse on the trace button while a request runs and the trace is closed, so the work in progress is not invisible. */
.topbar-btn-dot { position: absolute; top: 6px; right: 6px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent-primary); animation: trace-pulse 1.2s ease-in-out infinite; }
.theme-shadow .topbar-btn-dot { background: var(--accent-primary); }
.topbar-btn[aria-pressed="true"] { background: var(--bg-alt); color: var(--accent-primary); }
.theme-shadow .topbar-btn[aria-pressed="true"] { background: rgba(255, 255, 255, 0.1); color: var(--text-main); }

@media (max-width: 900px) { .topbar-sub { display: none; } }

/* ---------- the chat page inside the shell ---------- */

/* A row: the conversation, and the trace blade beside it when it is open. (The `div:has(.portal-body)` rule in index.css makes this a column; the
   doubled class wins over it.) */
div.chat-page.chat-page { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: row; height: auto; }

/* Stage 2, the conversation's own space. Everything here is scoped to .chat-page, so the embedded widget keeps its original layout.
   The scroll fades on .chat-window (index.css) and the messages' fade-in are deliberately left exactly as they are. */
.chat-page .portal-body { flex: 1 1 auto; min-width: 0; min-height: 0; max-width: 960px; padding: 0 1.5rem 1rem; }

/* The scroll fades on .chat-window are 40px at the top and 36px at the bottom (index.css). Padding of the same length keeps the first and last
   messages fully clear when the list is at rest, while anything scrolling past the edges still fades out and in exactly as before. */
.chat-page .chat-window { padding: 2.5rem 1.5rem 2.25rem; }

/* The empty chat: the brand and the example cards sit together in the middle of the free space, with the input docked below, instead of the
   cards hugging the top and a wide gap above the input. */
.chat-page .portal-body.initial-state-view .controls-footer { margin-top: 0; padding-top: 1rem; }
.chat-page .empty-brand { margin-top: auto; }
.chat-page .example-cards-container { margin-bottom: auto; }

/* Phones: the gutters stacked (page, then chat window) and left the text about three quarters of the screen's width. */
@media (max-width: 768px) {
  .chat-page .portal-body { padding: 0 0.5rem 0.5rem; }
  .chat-page .chat-window { padding: 2.5rem 0.5rem 2.25rem; }
  /* A reply has no visible bubble, so the bubble's own side padding was only taking width from the text. */
  .chat-page .message-bubble.ai { padding-left: 0.5rem; padding-right: 0.5rem; }
  .chat-page .empty-brand { padding-top: 1rem; }
}

/* Flat, no drop shadows on the bubbles or the input. The input's border was white in the light theme (invisible once the shadow went), so it gets the
   theme's soft blue border; the dark theme keeps the border it already had. (The .chat-window prefix outranks the theme rules in index.css, and
   nothing here applies to the embedded widget.) */
.chat-page .chat-window .message-bubble.message-bubble { box-shadow: none; }
.chat-page .chat-textarea,
.chat-page .chat-textarea:active { box-shadow: none; border-color: var(--border-color); }
.theme-shadow .chat-page .chat-textarea { border-color: var(--border-color); }

/* No lift on the input: the box and its buttons stay put on hover and press. The glowing border is a layer the size of the wrapper, and an inline
   textarea left a few pixels of line-box gap under itself, so that border sat low and showed as a second line under the box; a block textarea
   makes the wrapper exactly the box's size. */
.chat-page .chat-textarea { display: block; }
.chat-page .chat-input-wrapper:hover,
.chat-page .chat-input-wrapper:active,
.chat-page .chat-input-wrapper:hover::before,
.chat-page .chat-input-wrapper:active::before { transform: none; }
.chat-page .chat-input-wrapper:hover::before,
.chat-page .chat-input-wrapper:focus-within::before { box-shadow: none; }
.chat-page .chat-input-area button:hover:not(:disabled),
.chat-page .chat-input-area button:active:not(:disabled) { transform: none; box-shadow: none; }

/* The menus that open from the message box (the settings menu and the security scope picker, which hold an option wheel) and the tooltip. They were a fixed
   navy slate whatever the theme, so in the black and grey theme they were the one blue thing on the page. They now take the theme's popover surface, hairline
   and text colours, and the one floating shadow. (The embedded widget has no app shell, so it keeps its own look.) */
.app-shell .chat-overflow-wheel-popover,
.app-shell .chat-scope-picker-popover,
.app-shell .chat-tooltip-popover {
  background: var(--popover-bg) !important;
  border: 1px solid var(--border-color) !important;
  box-shadow: var(--float-shadow) !important;
}
.app-shell .chat-overflow-wheel-popover .option-wheel,
.app-shell .chat-scope-picker-popover .option-wheel {
  --ow-text-color: var(--text-muted) !important;
  --ow-active-color: var(--text-main) !important;
}
.app-shell .chat-scope-picker-popover > div:first-child { color: var(--text-muted) !important; }
.app-shell .chat-tooltip-popover a,
.app-shell .chat-tooltip-popover a:visited { color: var(--accent-primary) !important; }

/* The example questions are flat too: no shadow, no red glow in the dark theme, no lift on hover or press. The hover still changes the background and
   border, so they still answer the pointer. */
.chat-page .example-cards-container .query-card,
.chat-page .example-cards-container .query-card:hover,
.chat-page .example-cards-container .query-card:active { box-shadow: none; transform: none; translate: none; filter: none; }

/* Orange at the live edges, the places that react to you, rather than as a fill: the caret and text selection are orange, the active item in the rail
   has an orange edge, and the message box has a slow comet that circles it while it is hovered or focused (components/InputGlow.tsx). The comet runs
   blue at the tail to orange at the head, like the logo; the old border that flashed all the way round and faded is off in the app (the embedded
   widget keeps it). */
.chat-page .chat-input-wrapper::before { display: none; }
.input-glow {
  --glow-tail: #2f6fe0;
  --glow-head: var(--accent-primary);
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.theme-shadow .input-glow { --glow-tail: #2b4a8a; }
.chat-input-wrapper:hover .input-glow,
.chat-input-wrapper:focus-within .input-glow { opacity: 1; }
.input-glow rect {
  x: 1px;
  y: 1px;
  width: calc(100% - 2px);
  height: calc(100% - 2px);
  rx: 25px;
  fill: none;
  stroke: color-mix(in srgb, var(--glow-head) calc(var(--t) * 100%), var(--glow-tail));
  stroke-width: 2px;
  stroke-linecap: round;
  stroke-opacity: 0.32;  /* each dash is faint; where they overlap near the head they add up to a clear point */
  /* all the dashes end at the same point and move together: the head is where the dash ends */
  stroke-dashoffset: calc(var(--len) * 1px);  /* the start of the lap; the motion is built in InputGlow.tsx, paced by its size */
}
/* Without motion: no comet, and the box's own border takes the accent while it is focused. */
@media (prefers-reduced-motion: reduce) {
  .input-glow { display: none; }
  .chat-page .chat-input-wrapper:focus-within .chat-textarea { border-color: var(--accent-primary); }
}
.chat-page .chat-textarea { caret-color: var(--accent-primary); }
.app-shell ::selection { background: color-mix(in srgb, var(--accent-primary) 35%, transparent); }
/* Where you are: a short accent bar on the left edge of the selected rail item and conversation. It is a pseudo-element, because it used to be a background
   image that the dark theme's own `background:` on the active item reset, so in the dark theme it never showed. */
.app-rail .rail-item,
.rail-convo { position: relative; }
.app-rail .rail-item.active::before,
.rail-convo.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 24%;
  bottom: 24%;
  width: 3px;
  border-radius: 2px;
  background: var(--accent-primary);
  pointer-events: none;
}

/* Send: quiet while there is nothing to send, the accent once there is. (The rest of the buttons in that row keep the accent.) */
.chat-page .circle-icon-button.send-button:disabled svg,
.chat-page .circle-icon-button.send-button:disabled svg * { stroke: var(--text-muted) !important; }
.chat-page .circle-icon-button.send-button:disabled { opacity: 0.55; }
/* On hover the row's buttons take a soft accent fill; a solid one hid their own accent icon. */
.chat-page .icon-row-overlay .circle-icon-button:hover:not(:disabled) { background: var(--accent-soft); transform: none; box-shadow: none; }

.empty-brand { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding: 2rem 0 0.5rem; }
.empty-brand-title { margin: 6px 0 0; font-size: 1.55rem; font-weight: 700; color: var(--text-main); }
.empty-brand-sub { margin: 0; font-size: 0.9rem; color: var(--text-muted); }

/* ---------- phones: the rail is a drawer ---------- */

.rail-backdrop { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.45); z-index: 999; }

.app-rail-drawer {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  height: 100vh;
  height: 100dvh;
  width: min(300px, 86vw);
  transform: translateX(-102%);
  transition: transform 0.2s ease;
  z-index: 1000;
}
.app-rail-drawer.app-rail-open { transform: none; box-shadow: 0 0 40px rgba(0, 0, 0, 0.35); }

@media (prefers-reduced-motion: reduce) {
  .app-rail, .app-rail-drawer { transition: none; }
}

/* ---------- the quiet shell (an experiment: delete this whole block to go back) ----------
   The rail and the trace blade were filled panels with filled, outlined pills inside them, so they stood out next to the conversation. In the LIGHT
   theme the blue is now turned down about half way, the pills are gone (a faint tint and the orange tick say where you are), the dividers are softer and
   your own message bubble is a fainter tint. In the DARK theme nothing but the text changed: the rail's labels are muted. The orange accents are untouched. */
.app-rail .rail-item,
.app-rail .rail-convo-main { color: var(--text-muted); }
.app-rail .rail-item.active,
.rail-convo.active .rail-convo-main { color: var(--text-main); }

.app-shell:not(.theme-shadow) {
  --quiet-bg: color-mix(in srgb, var(--bg-alt) 55%, var(--bg-main));
  --quiet-line: color-mix(in srgb, var(--border-color) 80%, transparent);
  --quiet-hover: color-mix(in srgb, var(--text-main) 5%, transparent);
  --bubble-user-bg: color-mix(in srgb, var(--bg-alt) 38%, var(--bg-main));
  --bubble-user-border: transparent;
}
.app-shell:not(.theme-shadow) .app-rail { --rail-bg: var(--quiet-bg); border-right-color: var(--quiet-line); }
.app-shell:not(.theme-shadow) .trace-blade { background: var(--quiet-bg); border-left-color: var(--quiet-line); }
.app-shell:not(.theme-shadow) .trace-panel-head,
.app-shell:not(.theme-shadow) .app-topbar { border-bottom-color: var(--quiet-line); }

.app-shell:not(.theme-shadow) .app-rail .rail-item:hover,
.app-shell:not(.theme-shadow) .rail-convo:hover,
.app-shell:not(.theme-shadow) .app-rail .user-chip:hover,
.app-shell:not(.theme-shadow) .app-rail .rail-icon-btn:hover { background: var(--quiet-hover); }
.app-shell:not(.theme-shadow) .app-rail .rail-item.active,
.app-shell:not(.theme-shadow) .rail-convo.active { background: var(--quiet-hover); border-color: transparent; font-weight: 500; }
.app-shell:not(.theme-shadow) .rail-convo.active .rail-convo-main { font-weight: 500; }
.app-shell:not(.theme-shadow) .app-rail .rail-new { background: transparent; border-color: var(--quiet-line); }
.app-shell:not(.theme-shadow) .app-rail .user-chip { background: transparent; border-color: transparent; }

/* ==========================================================================
   1. GLOBAL RESETS & THEME VARIABLES
   ========================================================================== */
:root {
  /* The light theme: the dark theme's navy family in a light version. A light blue shared by the rail and your message bubble (so the bubble takes the same
     dark text as replies), deep navy text, and the same orange accent. (An orange-led light theme, a navy rail and a royal-blue bubble were tried and set aside.) */
  --bg-main: #ffffff;
  --bg-alt: #d9e5fb;            /* light blue: the rail, panels */
  --bg-surface: #ffffff;
  --bg-surface-hover: #cadcf7;
  --border-color: #bccdee;      /* hairlines */
  --ai-border-color: #ffffff;
  --user-border-color: #c3d0ea;
  --text-main: #14234a;         /* deep navy, from the dark theme's backdrop family */
  --text-muted: #6b7a9c;
  --text: #000000;
  --accent-primary: #c85a0c;    /* the orange: icons, labels, links, the avatar, focus */
  --accent-hover: #aa4a07;
  --accent-soft: #fde9d6;       /* a faint orange tint for hovers and chips */
  --accent-ring: rgba(200, 90, 12, 0.25);
  --accent-success: #10b981;    /* Soft emerald green for secure badges */
  --accent-danger: #ef4444;     /* Muted crimson for alerts */
  --card-tint: #eef2fa;         /* the example question cards */
  --tint-hover: #f5f8fd;
  --bubble-user-bg: #d9e5fb;    /* your messages: the rail's light blue, with the same dark text as replies */
  --bubble-user-border: #b4c8ee;
  --bubble-user-text: var(--text-main);
  --code-bg: #0f172a;           /* CodeBlock's syntax-highlighter background (Chat.tsx) */
  --code-border: #334155;
  --font-sans: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --follow-up-bg: rgba(27, 56, 112, 0.07);
  --hero-overlay: linear-gradient(
    rgba(238, 242, 250, 0.05) 0%,
    rgba(238, 242, 250, 0.45) 100%
  );
  /* Flat: the decorative shadow tokens are none, so every rule that still says box-shadow: var(--shadow...) is flat. Only things that float over the page
     (menus, popovers, tooltips) get a shadow, and they use --float-shadow. */
  --reverse-shadow: none;
  --shadow: none;
  --light-shadow: none;
  --shadow-hover: none;
  --shadow-hover-reversed: none;
  --light-shadow-hover: none;
  --shadow-dark-hover: none;
  --float-shadow: 0 8px 24px rgba(20, 35, 74, 0.16);
  --popover-bg: #ffffff;        /* menus and popovers */
  --on-accent: #ffffff;         /* text on a solid accent button */
  /* Surfaces and text for cards, tiles, rows, chips and inputs on the pages built from SelfService.css (Memory, Self Service, Sonic Health, the legal pages).
     Use these, never a hex: the dark theme overrides every one of them below. */
  --card-bg: #ffffff;           /* cards and tiles */
  --input-bg: #f4f7fd;          /* a row or field sunk a little into its card */
  --chip-bg: #e6edfb;           /* pills, chips, table headers */
  --line: var(--border-color);
  --line-strong: #a3b6dc;       /* an input's border, a hover edge */
  --text-soft: #3f4f78;         /* between --text-main and --text-muted */
}

/* THEME OVERRIDE: THE DARK THEME. (The class is still called theme-shadow from when this was a deliberately edgy red-and-black "Shadow" theme.)
   Black and grey, neutral (no colour tint), with orange as the only colour: the accent (icons, labels, links, the avatar), the live edges (the input's glow,
   the caret, the active rail item) and a few panel edges (the rail's and the trace blade's, --edge). Your own messages are a grey bubble. Real danger stays
   a clear red (--accent-danger). Anything that wants a dark surface should use the tokens below, not a hex, so the next change to this theme is one block. */
.theme-shadow {
  --bg-main: #0a0a0b;            /* the page */
  --bg-alt: #111113;
  --bg-surface: #151517;
  --bg-surface-hover: #1d1d20;
  --border-color: #262629;       /* hairlines: neutral grey */
  --ai-border-color: #2c2c30;
  --user-border-color: #3a3a40;
  --text-main: #e8e8ea;
  --text-muted: #8e8e95;
  --text: #f5f5f6;
  --accent-primary: #cf8a5a;     /* the one colour: a muted, slightly dusty orange (it was #f0883e, which glowed) */
  --accent-success: #3dba8c;
  --accent-danger: #ef4444;
  --accent-hover: #b9764a;
  --accent-soft: rgba(207, 138, 90, 0.12);
  --accent-ring: rgba(207, 138, 90, 0.25);
  --edge: color-mix(in srgb, var(--accent-primary) 60%, transparent);  /* an orange panel edge */
  --card-tint: #131315;
  --tint-hover: #1d1d20;
  --follow-up-bg: #151517;
  /* Component tokens */
  --panel-bg: #0e0e10;           /* rail, trace blade, nav */
  --popover-bg: #18181b;         /* menus and popovers */
  --on-accent: #0a0a0b;          /* text on a solid accent button: white on the muted orange is too faint */
  --card-bg: #131315;            /* cards and tiles */
  --input-bg: #0d0d0f;
  --line: #262629;
  --bubble-user-bg: #1b1b1e;     /* your messages: a faint lift off the page, no outline (the light theme's bubble is about this quiet) */
  --bubble-user-border: transparent;
  --bubble-user-text: #e8e8ea;
  --bubble-ai-bg: #0a0a0b;
  --bubble-ai-border: #0a0a0b;
  --bubble-ai-text: #e8e8ea;
  --filter-bg: #111113;
  --code-bg: #070708;
  --code-border: #1a1a1d;
  --hero-overlay: linear-gradient(rgba(8, 8, 9, 0.4), rgba(8, 8, 9, 0.85));
  --input-text: var(--text-main);
  --card-text: #e8e8ea;
  --loader-glow: none;
  --line-strong: #3a3a40;
  --chip-bg: #1d1d20;
  --text-soft: #b9b9bf;
  /* Flat theme: every decorative shadow is none; only things that float (menus, popovers, tooltips) get one, and it is plain black. */
  --shadow: none;
  --shadow-hover: none;
  --shadow-dark-hover: none;
  --float-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.theme-shadow, html body {
  background-color: #0a0a0b;
}

body, html {
  width: 100%;
  height: 100%;
  background-color: var(--bg-main) !important; 
  color: var(--text-main);
  font-family: var(--font-sans);
  overflow-x: hidden;
}

.theme-shadow .repo-banner {
  background-color: var(--bg-main) !important;
  border: 1px solid var(--border-color) !important;
  padding: 0.5rem 1rem;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
  box-shadow: var(--shadow-hover);
}

.theme-shadow .repo-banner input {
  background-color: var(--bg-main) !important;
  border: 1px solid var(--border-color) !important;
  color: var(--text-main) !important;
  padding: 0.5rem 1rem;
  border-radius: 6px;
  box-shadow: var(--shadow-hover);
  transition: all 0.2s ease;
}

.repo-banner input:active {
  box-shadow: none;
  transform: translateY(0);
  transition: all 0.2s ease;
}
.repo-banner input:active {
  box-shadow: none;
  transform: translateY(0);
  transition: all 0.2s ease;
  outline: none;
}

.repo-banner:hover{
  transform: translateY(-2px);
  box-shadow: var(--shadow-dark-hover);
  transition: all 0.2s ease;
}

.repo-banner input:hover {
  box-shadow: var(--shadow-dark-hover);
  transition: all 0.2s ease;
}

.repo-banner button {
  background-color: var(--bg-main) !important;
  border: 1px solid var(--border-color) !important;
  color: var(--text-main) !important;
  padding: 0.5rem 1rem;
  border-radius: 6px;
  box-shadow: var(--shadow-hover);
  transition: all 0.2s ease;
}

.repo-banner button:hover {
  box-shadow: var(--shadow-dark-hover);
  transition: all 0.2s ease;
}



/* Custom Clean Scrollbar */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background: var(--bg-main);
}
::-webkit-scrollbar-thumb {
  background: var(--border-color);
  border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--accent-primary);
}

/* ==========================================================================
   2. LANDING PAGE STYLES (Identity Gatekeeper)
   Three panels: a full-width top panel with Patchy at his laptop, and under it the sign-in panel and the logo panel. Every colour comes from the
   --ld-* variables below ("firelit": a dark space with orange as the only colour, Patchy the light source), so changing the look is one block.
   ========================================================================== */
.landing-page {
  --ld-top-bg: radial-gradient(ellipse 70% 120% at 50% 100%, #24211f 0%, #151517 55%, #0d0d0f 100%);
  --ld-top-glow: rgba(240, 136, 62, 0.5);
  --ld-edge: rgba(240, 136, 62, 0.55);
  --ps-accent: #f0883e;
  --ps-glint: #f5a25f;
  --ld-left-bg: linear-gradient(90deg, #17181b 0%, #131416 100%);
  --landing-ink: #f1e9de;
  --landing-ink-soft: #a89a8b;
  --landing-rule: rgba(241, 233, 222, 0.2);
  --ld-btn-bg: #f0883e;
  --ld-btn-ink: #0a0a0b;
  --ld-btn-hover: #f79a56;
  --ld-btn-wash: rgba(241, 233, 222, 0.08);
  --ld-right-bg: #0a0a0b;
  --ld-brand: #cf8a5a;
  --ld-right-glow: rgba(240, 136, 62, 0.14);
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100vh;
  background: var(--ld-left-bg);
}

/* The top panel. Patchy sits on its bottom edge, which is his floor (--ps-h is the height of his drawing). */
.landing-top {
  --ps-h: clamp(190px, 33vh, 310px);
  position: relative;
  flex: 0 0 auto;
  height: calc(var(--ps-h) * 1.03);
  width: 100%;
  background: var(--ld-top-bg);
  border-bottom: 1px solid var(--ld-edge);
  z-index: 3;
}
.landing-top::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 34% 90% at 50% 100%, var(--ld-top-glow) 0%, transparent 70%);
  pointer-events: none;
}
/* A large soft ring behind him, so the wide panel has a centre of gravity */
.landing-top::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: calc(var(--ps-h) * 2.1);
  height: calc(var(--ps-h) * 1.05);
  transform: translateX(-50%);
  border-radius: calc(var(--ps-h) * 2.1) calc(var(--ps-h) * 2.1) 0 0;
  border: 1px solid var(--ld-edge);
  border-bottom: none;
  opacity: 0.55;
  pointer-events: none;
}

/* the light he gives off: a wide warm glow on the floor behind him, and a ring that catches it */
.landing-top::before {
  background:
    radial-gradient(ellipse 21% 82% at 50% 100%, rgba(240, 136, 62, 0.4) 0%, rgba(240, 136, 62, 0.12) 50%, transparent 78%);
  animation: ld-flame 3.7s linear infinite;
  transform-origin: 50% 100%;
}
.landing-top::after {
  border-color: rgba(247, 168, 98, 0.8);
  opacity: 1;
  box-shadow: 0 0 14px rgba(240, 136, 62, 0.34), inset 0 0 22px rgba(240, 136, 62, 0.12);
  -webkit-mask-image: linear-gradient(to top, #000 30%, rgba(0, 0, 0, 0.35) 100%);
  mask-image: linear-gradient(to top, #000 30%, rgba(0, 0, 0, 0.35) 100%);
  animation: ld-flame-ring 2.9s linear infinite;
}
/* A flame does not pulse evenly: uneven steps, a quick dip, a flare */
@keyframes ld-flame {
  0% { opacity: 0.86; transform: scale(1); }
  7% { opacity: 0.68; transform: scale(0.97); }
  13% { opacity: 0.96; transform: scale(1.03); }
  21% { opacity: 0.76; transform: scale(0.98); }
  30% { opacity: 1; transform: scale(1.05); }
  38% { opacity: 0.8; transform: scale(0.99); }
  47% { opacity: 0.92; transform: scale(1.02); }
  55% { opacity: 0.7; transform: scale(0.97); }
  63% { opacity: 0.98; transform: scale(1.04); }
  72% { opacity: 0.8; transform: scale(1); }
  81% { opacity: 1; transform: scale(1.05); }
  90% { opacity: 0.74; transform: scale(0.98); }
  100% { opacity: 0.86; transform: scale(1); }
}
@keyframes ld-flame-ring {
  0% { opacity: 0.8; }
  9% { opacity: 0.6; }
  17% { opacity: 0.95; }
  26% { opacity: 0.72; }
  35% { opacity: 1; }
  46% { opacity: 0.66; }
  58% { opacity: 0.92; }
  67% { opacity: 0.7; }
  79% { opacity: 1; }
  89% { opacity: 0.68; }
  100% { opacity: 0.8; }
}
@media (prefers-reduced-motion: reduce) {
  .landing-top::before,
  .landing-top::after { animation: none; }
}

/* The lower half: two panels. Left (charcoal): the title, sign in, the notice under it, the legal links. Right (black): the logo and the guest sandbox. */
.landing-row {
  display: flex;
  flex: 1;
  min-height: 0;
  width: 100%;
}

.landing-left,
.landing-right {
  box-sizing: border-box;
  flex: 0 0 50%;
  width: 50%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
}

.landing-left {
  padding: 1.6rem clamp(1.25rem, 3vw, 2.75rem) 1rem;
  background: var(--ld-left-bg);
  z-index: 2;
}

.landing-right {
  align-items: center;
  background-color: var(--ld-right-bg);
  overflow: hidden;
  padding: 1.5rem clamp(1.25rem, 3vw, 2.75rem);
}
/* a faint warm light behind the logo */
.landing-right::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 50%, var(--ld-right-glow) 0%, transparent 62%);
  pointer-events: none;
}
.landing-right > * { position: relative; z-index: 1; }

/* Pointing at one side lights it and dims the other, so the choice (sign in, or the guest sandbox) reads at a glance. A warm light rises from the bottom of the
   panel under the pointer; the other panel is darkened. Keyboard focus counts the same as the pointer. Only on a screen that can hover and has two columns. */
@media (hover: hover) and (min-width: 769px) {
  .landing-left, .landing-right {
    transition: filter 0.4s ease, box-shadow 0.4s ease;
  }
  .landing-left:hover, .landing-left:focus-within,
  .landing-right:hover, .landing-right:focus-within {
    filter: brightness(1.1);
    box-shadow: inset 0 -90px 130px -70px rgba(240, 136, 62, 0.26);
  }
  .landing-row:has(.landing-left:hover, .landing-left:focus-within) .landing-right,
  .landing-row:has(.landing-right:hover, .landing-right:focus-within) .landing-left {
    filter: brightness(0.5);
  }
}
@media (prefers-reduced-motion: reduce) {
  .landing-left, .landing-right { transition: none; }
}

.landing-signin, .landing-guest { display: flex; flex-direction: column; gap: 0.9rem; width: 100%; max-width: 320px; }
.landing-signin { margin: 1.2rem 0 1rem; }
.landing-guest { align-items: center; margin-top: 1.4rem; }
.landing-guest .enter-btn { width: 100%; max-width: none; }

.landing-affiliate { font-size: 0.85rem; color: var(--landing-ink-soft); }
.landing-guest-note { color: var(--landing-ink-soft); font-size: 0.8rem; text-align: center; line-height: 1.4; margin: 0; }

.landing-logo { color: var(--landing-ink); } /* the one-colour logo */
.landing-name { margin-top: 0.7rem; font-size: 0.78rem; font-weight: 600; letter-spacing: 0.32em; text-transform: uppercase; color: var(--ld-brand); text-align: center; }

.landing-hero-text h2 {
  font-size: 2.2rem;
  letter-spacing: 0.5px;
  margin-bottom: 0.5rem;
  color: var(--landing-ink);
}

.landing-hero-text h3 {
  color: var(--landing-ink);
  font-size: 1.1rem;
  margin-bottom: 0.25rem;
}

.landing-hero-text h4 {
  color: var(--landing-ink-soft);
  font-size: 0.95rem;
  font-weight: 400;
}

.landing-notice {
  box-sizing: border-box;
  width: 100%;
  max-width: 420px;
  margin: 0 0 0.8rem;
  padding: 0.75rem 0.9rem;
  border-radius: 8px;
  background: rgba(10, 10, 11, 0.9);
  border: 1px solid rgba(240, 136, 62, 0.45);
  color: #f0e2d4;
  text-align: left;
}

.landing-links { display: flex; gap: 1rem; font-size: 0.8rem; }
.landing-links a { color: var(--landing-ink-soft); }

.enter-btn {
  width: 100%;
  max-width: 300px;
  background: var(--accent-primary);
  color: #ffffff;
  border: none;
  padding: 0.85rem 1.5rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: none;
}

.enter-btn:hover:not(:disabled) {
  background: var(--accent-hover);
  box-shadow: none;
  transform: translateY(-2px);
}
/* On the landing page the accent hover would vanish against some palettes, so each button lifts a shade or takes a faint wash instead. No lift. */
.landing-page .enter-btn:hover:not(:disabled) { transform: none; }
.landing-page .login-btn:hover:not(:disabled) { background-color: var(--ld-btn-hover) !important; }
.landing-page .guest-btn:hover:not(:disabled) { background-color: var(--ld-btn-wash) !important; }
.enter-btn:active:not(:disabled) {
  background: var(--accent-hover);
  transform: translateY(2px);
}
.enter-btn:disabled {
  background: var(--border-color);
  color: var(--text-muted);
  cursor: not-allowed;
  box-shadow: none;
}
/* ==========================================================================
   3. SECURE PORTAL CORE LAYOUT (Chat Interface)
   ========================================================================== */
.portal-container {
  display: flex;
  flex-direction: column;
  width: 100vw;
  min-height: 100vh;
  background-color: var(--bg-main); 
  color: var(--text-main);
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* Top Navigation Bar */
.menu-navigator {
  position: sticky;
  top: 0;
  z-index: 900;
  backdrop-filter: blur(10px);
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.75rem 1.5rem;
  background-color: var(--bg-main);
  border-bottom: 1px solid var(--border-color);
  z-index: 11;
  box-shadow: var(--shadow);
  transition: all 0.9s ease
}
.theme-shadow .menu-navigator {
  background-color: var(--panel-bg);
  border-bottom: 1px solid var(--border-color);
  box-shadow: var(--shadow);
}


.menu-navigator:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
  transition: 0.9s ease;
}
.nav-logo {
  font-weight: 700;
  letter-spacing: 0.5px;
  cursor: pointer;
  color: var(--accent-primary);
}

.nav-logo a, 
.nav-logo a:visited {
  font-weight: 700;
  letter-spacing: 0.5px;
  cursor: pointer;
  color: var(--accent-primary) !important; /* Forces the link to stay your primary accent */
  text-decoration: none;
}

.banner-context a {
  color: var(--text-main);
  text-decoration: underline;
  font-weight: 500;
}

.theme-shadow .banner-context {
  color: var(--text-muted)
}
.banner-context h4 {
  color: var(--text-main); /* Uses the soft sky-blue or ash-gray depending on theme */
  margin-bottom: 0.5rem;
}

.nav-links {
  display: flex;
  gap: 1.5rem;
  font-size: 0.9rem;
}

.nav-links span {
  color: #4b5563;
  cursor: pointer;
  transition: color 0.2s ease;
}

.nav-links span.active, .nav-links span:hover {
  color: var(--text-main);
  font-weight: 600;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 400px;
  /* box-shadow: var(--shadow); */
  transition: all 0.2s ease;
}

.form-group:hover {
  box-shadow: var(--shadow-hover);
  transition: all 0.2s ease;
}

.form-group label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-soft);
}

.form-group select {
  background-color: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--line-strong);
  padding: 0.75rem;
  border-radius: 6px;
  font-size: 1rem;
  outline: none;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

.form-group select:focus {
  border-color: var(--accent-primary);
}

.form-group select:hover {
  box-shadow: var(--shadow-hover) !important;
}


.nav-links span.nav-exit:hover {
  color: var(--accent-danger);
}

/* Hero Banner Frame */
.hero-banner {
  height: 110px;
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0 1.75rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  overflow: hidden;
  transition: background 0.4s ease, filter 0.3s ease;
  z-index: 10;
  transform: translateZ(0); /* Hardware acceleration */
  border-bottom-left-radius: 24px;
  border-bottom-right-radius: 24px;
  box-shadow: 
    0 20px 25px -5px rgba(0, 0, 0, 0.1), 
    0 10px 10px -5px rgba(0, 0, 0, 0.04),
    inset 0 1px 0px rgba(255, 255, 255, 0.2); /* Subtle inner highlight on the top edge */
  
  transition:all 0.9s ease;

}

.hero-banner:hover {
  transform: translateY(-2px) scale(1.005);
  box-shadow: 
    0 30px 35px -5px rgba(0, 0, 0, 0.15), 
    0 15px 15px -5px rgba(0, 0, 0, 0.08),
    inset 0 1px 0px rgba(255, 255, 255, 0.3);
}

/* Blue Gradient (Sonic / Light Theme) */
.hero-banner.theme-sonic,
.theme-sonic .hero-banner {
  background: linear-gradient(135deg, #0a1128 0%, #1c2541 45%, #2a4365 100%);
}

/* Red Gradient (Shadow / Dark Theme) */
.hero-banner.theme-shadow,
.theme-shadow .hero-banner {
  background: linear-gradient(135deg, #09090b 0%, #3a0007 50%, #7a0010 100%);
}

/* Subtle background watermark using the swoosh symbol */
.hero-banner::after {
  content: '';
  position: absolute;
  right: -30px;
  top: -40%;
  width: 280px;
  height: 180%;
  background-image: var(--hero-bg, url('/assets/white_swoosh-DvaQRXz0.png'));
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  opacity: 0.08;
  pointer-events: none;
  z-index: 1;
}

.theme-shadow .hero-banner {
  background: linear-gradient(135deg, #111115 0%, #7a0010 100%);
  border: 1px solid rgba(255, 255, 255, 0.08); /* Soft border to catch the light */
  box-shadow: 
    0 20px 30px -5px rgba(0, 0, 0, 0.7), 
    0 10px 15px -5px rgba(0, 0, 0, 0.5),
    inset 0 1px 0px rgba(255, 255, 255, 0.1);
}

.theme-shadow .hero-banner:hover {
  box-shadow: 
    0 35px 45px -5px rgba(0, 0, 0, 0.8), 
    0 20px 25px -5px rgba(0, 0, 0, 0.6),
    inset 0 1px 0px rgba(255, 255, 255, 0.15);
}

/* Logo icon positioning & glow */
.hero-logo-icon {
  height: 52px;
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.3));
  z-index: 2;
}

@media (max-width: 768px) {
  .hero-logo-icon {
    display: none;
  }
}

.banner-context {
  position: relative;
  z-index: 2;
}

.banner-context h3 {
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  margin: 0 0 0.15rem 0;
  color: #ffffff;
}

.banner-context h4 {
  font-size: 0.85rem;
  font-weight: 400;
  margin: 0 0 0.4rem 0;
  color: rgba(255, 255, 255, 0.75);
}

.badge {
  background: rgba(16, 185, 129, 0.15);
  color: #34d399;
  border: 1px solid rgba(16, 185, 129, 0.3);
  padding: 3px 10px;
  border-radius: 4px;
  font-size: 0.75rem;
  display: inline-block;
  font-family: monospace;
  font-weight: 600;
}

/* Hover feedback */
.hero-banner:hover {
  filter: brightness(1.08);
}

/* Main Body Framework */
.portal-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 0 1.5rem 1.5rem 1.5rem; /* Top: 0, Right: 1.5rem, Bottom: 1.5rem, Left: 1.5rem */  min-height: 0;
  max-width: 900px;
  width: 100%;
  margin: 0 auto;
  position: relative;
  background-color: var(--bg-main);
}

div:has(.portal-body) {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.remove-file-btn {
  all: unset;
  margin-left: 0.5rem;
  cursor: pointer;
  color: var(--accent-primary);
  font-weight: bold;
}
/* Chat History Matrix */
.chat-window {
  flex: 1;
  scroll-behavior: smooth;
  border-radius: 8px;
  padding: 1.25rem 1.5rem 2rem 1.5rem; /* Explicit: top, right, bottom, left */
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  /* Dual fade mask (Matches both WebKit and Standard spec) */
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0px,
    black 40px,
    black calc(100% - 36px),
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0px,
    black 40px,
    black calc(100% - 36px),
    transparent 100%
  );
}

.theme-shadow .chat-window {
  /* Dual fade mask (Matches both WebKit and Standard spec) */
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0px,
    black 40px,
    black calc(100% - 36px),
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0px,
    black 40px,
    black calc(100% - 36px),
    transparent 100%
  );
}

.message-bubble {
  max-width: 75%;
  padding: 0.85rem 1.2rem;
  border-radius: 16px;
  line-height: 1.5;
  font-size: 0.95rem;
  animation: fadeIn 0.2s ease-out forwards;
  box-shadow: var(--shadow);
}

/* Shown on a message Sonic wrote on its own when the conversation was opened (the "Message First" setting). */
.message-initiated-note {
  font-size: 0.72rem;
  opacity: 0.7;
  margin: -0.15rem 0 0.4rem;
}

/* A reply that is really a failure notice (see chatErrors.ts): a quiet retry button and a "Details" disclosure with the one technical line. */
.message-failure {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
  margin-top: 0.5rem;
  font-size: 0.8rem;
}
.message-failure-retry {
  background: transparent;
  color: var(--accent-primary);
  border: 1px solid var(--border-color);
  border-radius: 999px;
  padding: 0.25rem 0.8rem;
  font: inherit;
  cursor: pointer;
}
.message-failure-retry:hover:not(:disabled) { border-color: var(--accent-primary); }
.message-failure-retry:disabled { opacity: 0.5; cursor: default; }
.message-failure-details { color: var(--text-muted); }
.message-failure-details summary { cursor: pointer; user-select: none; }
.message-failure-details code { display: block; margin-top: 0.3rem; font-size: 0.75rem; overflow-wrap: anywhere; }

.message-sender {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  margin-bottom: 0.35rem;
  font-family: monospace;
  text-transform: uppercase;
}

/* Message Variations */
.message-bubble.system {
  align-self: center;
  background: #f8fafc;
  border: 1px dashed var(--border-color);
  color: #64748b;
  font-size: 0.85rem;
  max-width: 100%;
  text-align: center;
}
.message-bubble.system .message-sender { color: #64748b; }

.message-bubble.user {
  align-self: flex-end;
  background: var(--bubble-user-bg);
  color: var(--bubble-user-text);
  border: 1px solid var(--bubble-user-border);
  box-shadow: var(--shadow);
  z-index: 1;
}

.message-bubble.user .message-sender { color: var(--accent-primary); }

.message-bubble.ai {
  max-width: 100%;
  width: 100%;
  align-self: flex-start;
  background: var(--bg-main);       /* Off-white bubble for AI response clarity */
  border: none;
  color: #334155;
  box-shadow: none;
}
.message-bubble.ai .message-sender { color: var(--text-main); }

.message-bubble.ai.thinking {
  color: #94a3b8;
  font-style: italic;
  border-style: dashed;
  background: transparent;
  box-shadow: none;
}

.message-text {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.message-attachment-images {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.message-attachment-image {
  max-width: 240px;
  max-height: 240px;
  border-radius: 8px;
  object-fit: cover;
  display: block;
}

/* A picture Sonic made (a card with words on a photo): shown whole and large enough to judge the lettering, with a way to keep it. */
.message-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  max-width: 100%;
}

.message-card-image {
  max-width: min(100%, 520px);
  height: auto;
  border-radius: 10px;
  display: block;
}

.message-image-download {
  font-size: 0.75rem;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.35);
  color: inherit;
  text-decoration: none;
  background: transparent;
}

.message-image-download:hover {
  border-color: var(--accent-primary);
  color: var(--accent-primary);
}

.message-attachment-image-loading {
  width: 120px;
  height: 90px;
  border-radius: 8px;
  background: rgba(148, 163, 184, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  color: #94a3b8;
}

.message-live-browser {
  margin-bottom: 0.5rem;
  border: 1px solid rgba(148, 163, 184, 0.2);
  border-radius: 10px;
  overflow: hidden;
  background: rgba(15, 23, 42, 0.95);
}

.message-live-browser-label {
  padding: 0.4rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: #94a3b8;
  border-bottom: 1px solid rgba(148, 163, 184, 0.15);
}

.message-live-browser-frame {
  width: 100%;
  height: 360px;
  border: 0;
  display: block;
}

.message-text p {
  margin: 0.35rem 0;
}

.message-text p:first-child {
  margin-top: 0;
}

.message-text p:last-child {
  margin-bottom: 0;
}

.citation-link {
  color: var(--accent-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.citation-link-document {
  display: inline-flex;
  max-width: 100%;
  margin-top: 0.4rem;
  padding: 0.35rem 0.55rem;
  border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--accent-primary) 30%, transparent);
  background: color-mix(in srgb, var(--accent-primary) 8%, transparent);
  line-height: 1.35;
  text-decoration: none;
}

.citation-link-document:hover {
  background: color-mix(in srgb, var(--accent-primary) 16%, transparent);
  border-color: color-mix(in srgb, var(--accent-primary) 55%, transparent);
}

.theme-shadow .message-bubble.user {
  align-self: flex-end;
  background: var(--bubble-user-bg);
  color: var(--bubble-user-text);
  border: 1px solid var(--bubble-user-border);
  box-shadow: var(--shadow);
}

.theme-shadow .message-bubble.user .message-sender { color: var(--text-muted); }   /* the one orange label on the page was the loudest thing in the bubble */

.theme-shadow .message-bubble.ai {
  align-self: flex-start;
  background: var(--bubble-ai-bg);       /* Off-white bubble for AI response clarity */
  border: 1px solid var(--bubble-ai-border);
  color: #334155;
  color: var(--text);
}

.theme-shadow .follow-up-container button {
  background: var(--card-bg) !important;
  color: var(--text-main) !important;
  border: 1px solid var(--border-color) !important;
  box-shadow: var(--shadow);
}

.theme-shadow .follow-up-container p{
  color: var(--text);
}
/* ==========================================================================
   4. INTERACTIVE EXAMPLE CARDS
   ========================================================================== */
.example-cards-container {
  margin-top: 1.25rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

/* Why a file was not attached (a photo format the browser cannot read): a quiet line above the box, with a way to dismiss it. */
.attach-notice {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0 0 0.5rem;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--border-color);
  border-radius: 12px;
  background: var(--bg-main);
  color: var(--text);
  font-size: 0.85rem;
  line-height: 1.4;
}

.attach-notice button {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 0.9rem;
}

/* Four cards (the portfolio set) sit as a 2 x 2 instead of leaving one alone on a second row. */
.example-cards-container:has(.query-card:nth-child(4):last-child) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.query-card {
  background:var(--bg-main);
  border: 1px solid var(--user-border-color);
  padding: 1rem;
  border-radius: 16px;
  cursor: pointer;
  transition: all 0.2s ease;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-shadow: var(--shadow);
  color: var(--text);
}


.theme-shadow .query-card {
  background: var(--bg-main);                  
  border: 1px solid var(--border-color);
  filter: var(--loader-glow);         
}

.query-card:hover {
  background: var(--tint-hover);
  border-color: var(--accent-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
  translate: translateY(-2px);
}

.theme-shadow .query-card:hover {
  background: var(--bg-surface-hover);
  border-color: var(--accent-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}

.query-card:active {
  transform: translateY(2px);
  box-shadow: 0 1px 3px rgba(0,0,0,0.02);
}

.query-card p {
  font-size: 0.9rem;
  color: var(--text);
  line-height: 1.4;
  margin-bottom: 0.75rem;
}

/* What kind of question it is ("About Jack", "Watch it work"): quiet, so the question stays the thing you read. */
.query-card-label {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 0.4rem;
}

.query-card span {
  font-size: 0.75rem;
  color: var(--accent-primary);
  font-weight: 600;
  align-self: flex-end;
}

/* ==========================================================================
   5. CONTROLS FOOTER & FILTERS DRAWER
   ========================================================================== */
.controls-footer {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.chat-input-wrapper {
  position: relative;
  flex: 1;
  z-index: 0;
  
  transition: all 0.2s ease;
}

.chat-input-wrapper .chat-input {
  width: 100%
}

/* Animated border layer */
.chat-input-wrapper::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 25px;
  padding: 2px; /* border thickness */
  pointer-events: none;
  transition: all 0.2s ease;
  background: linear-gradient(
    90deg,
    transparent 0%,
    #00aaff 20%,
    #00ffcc 40%,
    transparent 60%
  );
  background-size: 400% 400%;
  z-index: 0;
  @keyframes borderLoop {
    0%   { background-position: 0% 0%; }
    25%  { background-position: 100% 0%; }
    50%  { background-position: 100% 100%; }
    75%  { background-position: 0% 100%; }
    100% { background-position: 0% 0%; }
  }

  /* Turn gradient into a border */
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;

  opacity: 0;
  transition: opacity 0.4s ease;
}

/* Hover activates the glowing border */
.chat-input-wrapper:hover::before {
  opacity: 1;
  animation: borderLoop 3s linear infinite;
  transform: translateY(-2px);
  transition: all 0.2s ease;
  box-shadow: var(--shadow-hover-reversed);
}

.chat-input-wrapper:active::before {
  transform: translateY(2px);
}
.chat-input-wrapper:hover {
  transform: translateY(-2px);
  transition: all 0.2s ease;
}
.chat-input-wrapper:focus-within::before {
   opacity: 1;
   animation: borderLoop 3s linear infinite;
   box-shadow: var(--shadow-hover);
}

.chat-input-wrapper:active {
  transform: translateY(2px);
}


/* Looping animation */
@keyframes borderLoop {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 20%; }
}

.chat-input {
  position: relative;
  z-index: 1;
}

.chat-input-area {
  display: flex;
  background: var(--bg-main);
  z-index: 2;
}

.chat-input-area input:focus {
  border-color: transparent; /* hide real border */
  opacity: 1;
  animation: borderLoop 3s linear infinite;
}

.chat-input-area input:hover {
  /* border-color: var(--accent-primary); */
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}

.chat-input-area input:active {
  transform: translateY(2px);
  box-shadow: none;
}

.chat-input-area input {
  flex: 1;
  background: var(--bg-surface);
  border: 1px solid var(--ai-border-color);
  padding: 0.85rem 1.2rem;
  border-radius: 25px;
  color: var(--text);
  font-size: 0.95rem;
  outline: none;
  transition: all 0.2s;
  background: var(--bg-main);
  /* Pulls a top shadow upward over the scrolling messages */
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.15);;
  z-index: 1;

}

.theme-shadow .chat-input-area input {
  border: 1px solid var(--border-color)
}

.chat-input-area input:focus {
  /* border-color: var(--accent-primary); */
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.chat-input-area input::placeholder {
  color: #94a3b8;
}

.chat-input-area .icon-button svg,
.chat-input-area .icon-button svg * {
    stroke: var(--accent-primary) !important;
    fill: none !important;
}


.circle-icon-button {
  all: unset;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: none;
  border: 1px solid var(--bg-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s ease;
}

.theme-shadow .circle-icon-button {
  border: none;
}

.feedback-actions .circle-icon-button:hover:not(:disabled) {
  transform: scale(1.1);
  box-shadow: none;
}
.circle-icon-button:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}

.circle-icon-button:active:not(:disabled) {
  transform: translateY(2px);
  
}

.circle-icon-button.trace-active {
  border: 1px solid var(--border-color) !important;
  background: var(--accent-primary) !important;
  box-shadow: var(--shadow-hover);
  filter:brightness(1.2)
}

.theme-shadow .circle-icon-button:hover:not(:disabled) {
  transform: translateY(-2px);
  background: var(--accent-primary);
  box-shadow: var(--shadow-hover);
}

.theme-shadow .circle-icon-buttonactive:not(:disabled) {
  transform: translateY(2px);
  background: var(--accent-primary);
  box-shadow: var(--shadow-hover);
}
.theme-shadow .circle-icon-button:hover {
  background: var(--accent-primary);
}

.circle-icon-button svg,
.circle-icon-button svg * {
  stroke: var(--accent-primary) !important;
  fill: none !important;
}

.theme-shadow .circle-icon-button.trace-active {
  border: 1px solid var(--border-color) !important;
  background: var(--accent-primary) !important;
  box-shadow: var(--shadow-hover);
}

.theme-shadow .desktop-trace-sidebar {
  border: 1px solid var(--border-color) !important;
  background: var(--card-bg) !important;
  box-shadow: var(--shadow);
}

.theme-shadow .trace-step {
  border: 1px solid var(--border-color) !important;
  background: var(--bg-secondary) !important;
  box-shadow: var(--shadow-hover);
}

@media (max-width: 768px) {
  .theme-shadow .mobile-trace-modal-content {
    border: 1px solid var(--border-color) !important;
    background: var(--bg-secondary) !important;
    box-shadow: var(--shadow);
  }
  .theme-shadow .mobile-trace-pill-container button {
    border: 1px solid var(--border-color) !important;
    background: var(--bg-secondary) !important;
    box-shadow: var(--shadow);
  }
}
.icon-button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.mobile-trace-pill{
  z-index:5
}
.icon-button:hover:not(:disabled) {
  opacity: 0.8;
  transform: translateY(-1px);
}

/* Force icon color */
.icon-svg,
.icon-svg * {
  stroke: var(--accent-primary) !important;
  fill: none !important;
}

.input-stack {
  display: flex;
  flex-direction: column;
  width: 100%;
  position: relative;
}

.icon-row {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-top: 0.5rem;
}

.chat-textarea {
  width: 100%;
  resize: none;
  min-height: 64px;
  max-height: 200px;
  overflow-y: auto;
  padding: 0.85rem 1.2rem 2.5rem; /* extra bottom padding for icons */
  border-radius: 25px;
  border: 1px solid var(--ai-border-color);
  background: var(--bg-main);
  color: var(--text);
  font-size: 0.95rem;
  box-shadow: var(--shadow);
  outline: none;
  transition: all 0.2s;
}
.chat-tooltip-popover { box-shadow: var(--float-shadow); }

.theme-shadow .chat-tooltip-popover {
  background: var(--popover-bg) !important;
  border: 1px solid var(--border-color) !important;
  box-shadow: var(--float-shadow);
}

.theme-shadow .chat-tooltip-popover s,
.theme-shadow .chat-tooltip-popover strong,
.theme-shadow .chat-tooltip-popover em {
  color: #cbd5e1 !important;
}
.theme-shadow .chat-tooltip-popover a,
.theme-shadow .chat-tooltip-popover a:visited {
  color: var(--accent-primary) !important;
  text-decoration: underline;
}

.theme-shadow .chat-tooltip-popover a:hover {
  color: #38bdf8 !important;
}


.chat-tooltip-popover a,
.chat-tooltip-popover a:visited {
  color: #00f2fe !important;
  text-decoration: underline;
}

.chat-tooltip-popover a:hover {
  color: #38bdf8 !important;
}

.theme-shadow .chat-textarea {
  border: 1px solid var(--border-color)
}
.chat-textarea:active {
  box-shadow: none;
}

.icon-row-overlay {
  position: absolute;
  right: 0.75rem;
  bottom: 0.75rem;
  display: flex;
  gap: 0.5rem;
}

.chat-input-area .submit-button,
.chat-input-area .clear-button {
  background: var(--accent-primary);
  color: #ffffff;
  border: none;
  padding: 0 1.75rem;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: var(--shadow);
}

.theme-shadow .chat-input-area .clear-button {
  background-color: #000000 !important;
}

.chat-input-area button:hover:not(:disabled) {
  background: var(--accent-hover);
  box-shadow: var(--shadow-hover);
  transform: translateY(-2px);
}

.chat-input-area button:active:not(:disabled) {
  background: var(--accent-hover);
  transform: translateY(2px);
  box-shadow: 0 1px 3px rgba(0,0,0,0.02);
}

.chat-input-area button:disabled {
  border: none !important;
  color: #94a3b8;
  border: 1px solid #cbd5e1;
  cursor: not-allowed;
}

/* Security Dropdown Filter Component Row */
.filter-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.85rem;
  background: var(--bg-alt); 
  border: 1px solid var(--user-border-color);
  border-radius: 16px;
  box-shadow: var(--shadow);
  transition: all 0.2s ease;
}

.theme-shadow .filter-row {
  background: var(--bg-main); 
  border: 1px solid var(--border-color);
}

.theme-shadow .filter-row:hover {
  background: var(--bg-alt);
  border-color: var(--accent-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}

.filter-row:hover {
  background: var(--tint-hover);
  border-color: var(--accent-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}

.filter-row label {
  font-size: 0.8rem;
  color: var(--text-main);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.rag-mode-toggle-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  margin-left: auto;
}

.rag-mode-toggle-label:has(input:disabled) {
  cursor: not-allowed;
  opacity: 0.5;
}

.switch {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
}

.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.switch-track {
  position: absolute;
  inset: 0;
  background: var(--border-color);
  border-radius: 999px;
  transition: background 0.2s ease;
}

.switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: #ffffff;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  transition: transform 0.2s ease;
}

.switch input:checked + .switch-track {
  background: var(--accent-primary);
  filter: brightness(1.2);
}

.switch input:checked + .switch-track .switch-thumb {
  transform: translateX(16px);
}

.switch input:disabled {
  cursor: not-allowed;
}

.filter-row select {
  background: var(--bg-main);
  color: #334155;
  border: 1px solid var(--border-color);
  padding: 0.35rem 0.6rem;
  border-radius: 20px;
  font-size: 0.85rem;
  outline: none;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.2s ease;
}

@media (max-width: 768px) {
  .filter-row {
    /* Was flex-direction: column, which puts every child (label, select, toggle) on its
     own line — 3 rows. flex-wrap lets them share rows instead; whichever item gets
     flex: 0 0 100% below is the one forced onto its own line, everything else just falls
     in naturally around it. */
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
  }
  .filter-row select {
    flex: 1;
    min-width: 0;
  }
  .switch-track {
    justify-content: end;
    display: flex;
  }
  .rag-mode-toggle-label {
    /* Forced onto its own row 2, leaving the label + select to share row 1. */
    flex: 0 0 100%;
    margin-left: 0;
    /* Now that this label spans the full row, space its own two children (the text and
       the switch) apart instead of letting them bunch together on the left. */
    justify-content: space-between;
  }
}

.filter-row select:focus {
  border-color: var(--accent-primary);
}

.filter-row select:hover {
  box-shadow: var(--shadow-hover);
  transition: all 0.2s ease;
}
.affiliate-select:hover {
  background: #f8fafc;
  border-color: var(--accent-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}
select:not(:-internal-list-box):not([multiple]) option {
  background: var(--bg-secondary) !important;
  color: var(--text-main) !important;
}

.theme-shadow .filter-row select { 
  background: var(--bg-secondary) !important;
  border: 1px solid var(--border-color) !important;
  box-shadow: var(--shadow);
  color: var(--text-main) !important;
}
.nav-clear:hover {
  color: #f8fafc !important;
  text-decoration: underline;
}
.export-button {
  background-color: var(--accent-primary);
  color: '#ffffff';
  marginLeft: '0.5rem'
}


/* Keyframe Animations */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   6. DYNAMIC STATE TRANSITIONS
   ========================================================================== */
/* FIX: Move the sizing limits here so the dashboard column stays 
   perfectly compact, centered, and sized the same before and after chatting */


.portal-body.initial-state-view {
  flex: 1;
}

/* Keeps cards container compact and perfectly preserves its original size */
.portal-body.initial-state-view .example-cards-container {
  flex: none;
}

/* Forces the footer to pin to the baseline by consuming the empty space above it */
.portal-body.initial-state-view .controls-footer {
  margin-top: auto;
  padding-top: 2rem; 
}

/* Ensure smooth auto-scroll tracking inside layout calculations */


/* ==========================================================================
   7. LOADING ANIMATIONS
   ========================================================================== */


/* Custom Sonic Graph Loader Container */
.sonic-loader-container {
  display: flex;
  flex-direction: row; /* Align loader and status text horizontally */
  align-items: center;
  justify-content: flex-start; /* Push everything to the left */
  gap: 16px;
  margin: 16px 0 16px 12px; /* Margin on the left matches the AI avatar/bubble alignment */
  width: 100%;
}

.sonic-ring-loader {
  width: 32px; /* Slightly tighter profile to match text height */
  height: 32px;
  border: 4px solid rgba(255, 204, 0, 0.15);
  border-top: 4px solid #ffcc00;
  border-radius: 50%;
  /* Per-segment easing lives on the keyframes themselves below (that's the only way to get a
     different feel per phase) — linear here is just the harmless fallback. */
  animation: sonic-spin 5.4s linear infinite;
  position: relative;
  flex-shrink: 0; /* Prevent the ring from squeezing */
}

/* Inner pulsing core */
.sonic-ring-loader::after {
  content: '';
  position: absolute;
  top: 4px;
  left: 4px;
  right: 4px;
  bottom: 4px;
  border-radius: 50%;
  background: rgba(255, 204, 0, 0.2);
  animation: sonic-pulse 1.6s ease-in-out infinite;
}

/* Text status styling next to the loader */
.agent-status-text {
  font-family: var(--font-sans);
  font-size: 0.9rem;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Shadow Engine Theme Override */
.theme-shadow .sonic-ring-loader {
  border: 4px solid rgba(207, 138, 90, 0.15); /* Faint track in the accent */
  border-top: 4px solid var(--accent-primary); /* The spinning arc */
  box-shadow: none;
}

.theme-shadow .sonic-ring-loader::after {
  background: rgba(207, 138, 90, 0.25);
}

/* Animations */
@keyframes sonic-spin {
  /* One pull-back, then ONE continuous wind-down. Each keyframe's animation-timing-function governs the segment from that keyframe to the next.
     The spin is a single segment (-24deg to 16 whole turns) on a single easing curve, so the speed rises quickly to about ten turns a second and then
     falls away smoothly the whole way: nothing in it can stall and re-start, and the last turn, the last quarter turn and the last few degrees each take
     longer than the one before, until it comes to rest exactly at the top (5760deg is a multiple of 360, so the loop restarts from where it stopped).
     The last 5% of the cycle holds still at the top before the next pull-back. */
  0% { transform: rotate(0deg); animation-timing-function: ease-out; }                     /* wind-up: a quick pull back to the cocked position */
  7% { transform: rotate(-24deg); animation-timing-function: cubic-bezier(0.2, 0.3, 0.15, 1); }  /* release, then the wind-down: 16 turns, fast then ever slower */
  95% { transform: rotate(5760deg); }
  100% { transform: rotate(5760deg); }
}
/* Keeps the text pulsing while waiting */
.loading-text {
  color: #94a3b8;
  font-size: 0.95rem;
  animation: text-pulse 1.5s ease-in-out infinite;
}

@keyframes text-pulse {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

/* --- Mobile Responsive Overrides --- */
@media (max-width: 768px) {
  /* One column: Patchy's panel on top (smaller), then the sign-in copy */
  .landing-page {
    flex-direction: column;
    height: auto;
    min-height: 100vh;
    overflow-y: auto;
  }

  .landing-top { --ps-h: clamp(150px, 24vh, 200px); }

  /* One column, in this order: logo and name, title, sign in, guest, notice, links. The two panels dissolve (display: contents) so their parts can be
     ordered freely. */
  .landing-row { flex-direction: column; padding: 1.8rem 1.5rem 1rem; gap: 1.4rem; background: var(--ld-left-bg); align-items: center; text-align: center; }
  .landing-left, .landing-right { display: contents; }
  .landing-right::before { display: none; }
  .landing-logo { order: 0; margin-bottom: -0.8rem; }
  .landing-name { order: 1; margin-top: 0; font-size: 0.7rem; }
  .landing-id { order: 2; }
  .landing-hero-text h2 { font-size: 1.9rem; }
  .landing-hero-text h3 { font-size: 1rem; }
  .landing-hero-text h4 { font-size: 0.9rem; }
  .landing-signin { order: 3; max-width: 100%; margin: 0; }
  .landing-affiliate { text-align: center; }
  .landing-guest { order: 4; max-width: 100%; margin: 0; }
  .landing-notice { order: 5; margin: 0; }
  .landing-links { order: 6; }
}

/* Hide mobile toggle by default on desktop */
.mobile-menu-toggle {
  display: none;
}

/* Counterpart to .desktop-only below — hidden by default (desktop), shown under 768px. */
.mobile-only {
  display: none;
}

.mobile-drawer {
  display: none;
}

/* --- Mobile Breakpoint (Phones under 768px) --- */
@media (max-width: 768px) {
  /* Hide standard desktop link row */
  .desktop-only {
    display: none !important;
  }

  .mobile-only {
    display: inline;
  }

  /* Show mobile hamburger button */
  .mobile-menu-toggle {
    display: block;
  }

  .hamburger-btn {
    background: var(--accent-primary) !important;
    border: 1px solid var(--accent-primary) !important;
    color: white !important; /* Dark text for Sonic mode visibility */
    font-size: 1.2rem;
    padding: 0.2rem 0.5rem;
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .theme-shadow .mobile-drawer {
    box-shadow: var(--shadow);
    background: var(--bg-main) !important;
    border: 1px solid var(--border-color) !important;
    color: var(--text-main) !important;
    border-bottom-left-radius: 16px;
    border-bottom-right-radius: 16px;
  }
  /* Slick Mobile Slide-down Drawer */
  .mobile-drawer {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 60px;
    left: 0;
    right: 0;
    background: rgba(18, 24, 36, 0.98);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    z-index: 1000;
    padding: 1rem;
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
    animation: slideDown 0.2s ease-out forwards;
  }
  .theme-shadow .theme-toggle-btn-mobile {
    
    background: var(--bg-secondary) !important;
  }
  .mobile-drawer-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.85rem;
    color: #94a3b8;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    margin-bottom: 0.5rem;
  }

  .theme-toggle-btn-mobile {
    background: #1e293b;
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    color: #f8fafc;
    font-weight: 500;
  }

  .mobile-drawer-links {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }

  .mobile-drawer-links span {
    padding: 0.75rem 1rem;
    border-radius: 6px;
    color: #f1f5f9;
    font-size: 1rem;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.03);
    transition: background 0.2s;
  }

  .mobile-drawer-links span:active {
    background: rgba(255, 255, 255, 0.1);
  }

  .mobile-logout {
    color: #ef4444 !important;
    font-weight: 600;
  }
}
.mobile-actions-group {
  display: none;
}

@media (max-width: 768px) {
  /* Show mobile actions group on phones */
  .mobile-actions-group {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .example-cards-container .query-card:not(:first-child) {
    display: none !important;
  }
  .message-bubble {
    max-width: 97% !important;
  }

  .citation-link-document {
    display: block;
    width: 100%;
    font-size: 0.84rem;
  }
}

  .mobile-quick-disconnect {
    background: rgba(239, 68, 68, 0.15);
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: #f87171;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.35rem 0.6rem;
    border-radius: 6px;
    cursor: pointer;
  }



@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ===================================== */
/* ==========================================================================
   BTY EMBEDDED WIDGET THEME
   ========================================================================== */
.bty-embed-container {
  --bg-main: #121316;
  --bg-surface: #1c1e22;
  --bg-surface-hover: #23262b;
  --border-color: rgba(56, 194, 222, 0.25);
  --ai-border-color: #23262b;
  --user-border-color: rgba(56, 194, 222, 0.35);
  --text-main: #e7eaee;
  --text-muted: #9aa1ab;
  --text: #e7eaee;
  --accent-primary: #38C2DE;
  --bubble-user-bg: rgba(56, 194, 222, 0.12);

  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0 !important;
  background: var(--bg-main);
  color: var(--text-main);
}

/* Bound the height chain so the footer can genuinely pin, chat length can't push it off */
.bty-embed-container div:has(.portal-body) {
  flex: 1;
  min-height: 0;
}
.bty-embed-container .portal-body { min-height: 0; }
.bty-embed-container .chat-window { min-height: 0; }
.bty-embed-container .controls-footer {
  margin-top: auto;
  padding: 0 1.25rem 1.25rem;
}

/* Restyle components instead of masking them */
.bty-embed-container .message-bubble.ai {
  background: var(--bg-surface);
  border-color: var(--border-color);
  color: var(--text-main);
}
.bty-embed-container .message-bubble.user {
  background: var(--bubble-user-bg);
  border-color: var(--border-color);
  color: var(--text-main);
}
.bty-embed-container .query-card {
  background: var(--bg-surface);
  border-color: var(--border-color);
  color: var(--text-main);
}
.bty-embed-container .query-card:hover {
  background: var(--bg-surface-hover);
  border-color: var(--accent-primary);
}
.bty-embed-container .chat-input-area input,
.bty-embed-container .chat-textarea {
  background: var(--bg-surface);
  border-color: var(--border-color);
  color: var(--text-main);
}

.bty-embed-container .citation-link {
  color: var(--accent-primary);
}

.bty-embed-container .citation-link-document {
  border-color: var(--border-color);
  background: rgba(56, 194, 222, 0.08);
}

.bty-loader-container {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem;
}

.bty-loader-dots {
  display: flex;
  gap: 6px;
}

.bty-loader-dots span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent-primary);
  animation: bty-bounce 1.1s ease-in-out infinite;
}

.bty-loader-dots span:nth-child(2) { animation-delay: 0.15s; }
.bty-loader-dots span:nth-child(3) { animation-delay: 0.3s; }

@keyframes bty-bounce {
  0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
  40% { transform: scale(1); opacity: 1; }
}