/* =============================================================================
   PrivacyWall Design System — AI module  (DRAFT)
   Built from the "Glance" entry point in the approved search, travel and
   shopping designs, plus the AI mockups in the marketing assets. The visual
   language is settled; the conversation surface has not been signed off, so
   treat the layout here as a proposal and the tokens as final.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   THREAD
   ----------------------------------------------------------------------------- */
.pw-thread { display: flex; flex-direction: column; gap: var(--pw-space-10); }

.pw-msg { display: flex; gap: var(--pw-space-5); max-width: 100%; }
.pw-msg__avatar {
  display: grid; place-items: center;
  width: 30px; height: 30px; flex: 0 0 auto;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-color-purple-50);
  color: var(--pw-color-purple-600);
}
[data-pw-theme="dark"] .pw-msg__avatar,
html.dark .pw-msg__avatar { background: rgba(122, 90, 248, .18); color: #c3b5fd; }
.pw-msg__body { min-width: 0; flex: 1; }
/* The orb brings its own body, so the slot drops its tinted disc -- in both
   themes, since the dark rule above is more specific than a modifier alone. */
.pw-msg__avatar.pw-msg__avatar--orb,
[data-pw-theme="dark"] .pw-msg__avatar.pw-msg__avatar--orb,
html.dark .pw-msg__avatar.pw-msg__avatar--orb { background: none; }
.pw-msg__avatar--orb .pw-orb { --pw-orb-size: 30px; }

/* Shimmer text: a working label, dimmed, with a band of full-strength text
   sweeping through it (the controller moves the band). Sized to its words so
   the band crosses the label, not the row. Without motion it keeps its own
   colour, still. A label that belongs to a step shimmers only while that step
   is the one in progress. */
.pw-shimmer-text {
  width: fit-content;
}
.pw-shimmer-text.is-shimmering:not(.is-still) {
  background: linear-gradient(90deg,
    var(--pw-shimmer-base) 0%, var(--pw-shimmer-base) 40%,
    var(--pw-shimmer-band) 50%,
    var(--pw-shimmer-base) 60%, var(--pw-shimmer-base) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  --pw-shimmer-base: color-mix(in srgb, var(--pw-fg-primary) 50%, transparent);
  --pw-shimmer-band: color-mix(in srgb, var(--pw-fg-primary) 95%, transparent);
}
/* The label an answer shows before it has words. It is the whole body, so it
   sits on the orb's centre line. */
:is(.pw-activity__step, .pw-work__step):not(.is-active) .pw-shimmer-text {
  background: none; -webkit-text-fill-color: currentColor;
}
.pw-msg__working { margin: 0; }
.pw-msg__body:has(> .pw-msg__working:only-child) { align-self: center; }

/* -----------------------------------------------------------------------------
   DOT MARKS -- the orb and the Glance mark
   Two marks in one material: dots in the AI tint on a lit body, drawn by the
   controller in pw-components.js. The ORB is the assistant in a conversation,
   a globe whose land comes from a baked 96 x 48 mask (ds/gen/orb_land.py). The
   GLANCE MARK is the answer above the search results: its sparkle, as a grid
   of dots in the medallion's rounded square.

   Six states, set as `data-state` and read off the markup:
     standby     still. Ready, and not asking for anything. The orb rests as one
                 big dot and every other state grows the globe out of it.
     thinking    orb: a slow turn, dots firing.   glance: a ripple from the sparkle.
     building    orb: fills in south to north.    glance: fills in bottom to top.
     generating  orb: a fast turn and a meridian. glance: a glint, corner to corner.
     waiting     still, and ringed. It is the reader's turn. Orb only: a Glance
                 answers the search and never asks back.
     error       danger colours and one shake. The Glance mark also re-forms into "!".
   Motion never carries a state alone. Each pairs with a visible label, and
   under `prefers-reduced-motion` each still draws its own distinct frame.
   Everything here that is not a dot collapses under reduced motion with the
   rest of the system.
   ----------------------------------------------------------------------------- */
.pw-orb, .pw-glance-mark {
  position: relative;
  display: inline-block; flex: none; vertical-align: middle;
  /* The dots are drawn in the AI mesh (the logo's cyan, red and amber) by the
     controller; `color` is only the flat colour a state such as error takes. */
  color: var(--pw-ai-mesh-b);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pw-ai-mesh-b) 12%, transparent);
}
.pw-mark__canvas { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; }

.pw-orb {
  --pw-orb-size: 40px;
  --pw-mark-radius: var(--pw-radius-circle);
  width: var(--pw-orb-size); height: var(--pw-orb-size);
  border-radius: var(--pw-mark-radius);
  /* Lit from the upper left and darkening toward the limb: enough volume that
     the dots read as sitting ON a sphere rather than inside a circle. */
  background:
    radial-gradient(circle at 78% 20%, color-mix(in srgb, var(--pw-ai-mesh-a) 16%, transparent), transparent 62%),
    radial-gradient(circle at 24% 80%, color-mix(in srgb, var(--pw-ai-mesh-c) 18%, transparent), transparent 62%),
    radial-gradient(circle at 34% 28%,
      var(--pw-bg-surface) 0%, var(--pw-bg-surface) 40%,
      color-mix(in srgb, var(--pw-ai-mesh-b) 12%, var(--pw-bg-surface)) 100%);
}
.pw-orb--xs  { --pw-orb-size: 24px; }
.pw-orb--sm  { --pw-orb-size: 32px; }
.pw-orb--lg  { --pw-orb-size: 64px; }
.pw-orb--xl  { --pw-orb-size: 96px; }
.pw-orb--2xl { --pw-orb-size: 160px; }

/* The medallion's footprint, so it drops into the Glance head without moving
   the title. Flat and faintly lit rather than a sphere -- it is a badge. */
.pw-glance-mark {
  --pw-glance-mark-size: 28px;
  --pw-mark-radius: var(--pw-radius-md);
  width: var(--pw-glance-mark-size); height: var(--pw-glance-mark-size);
  border-radius: var(--pw-mark-radius);
  background:
    radial-gradient(90% 90% at 100% 0%, color-mix(in srgb, var(--pw-ai-mesh-a) 14%, transparent), transparent 70%),
    radial-gradient(90% 90% at 0% 100%, color-mix(in srgb, var(--pw-ai-mesh-c) 16%, transparent), transparent 70%),
    linear-gradient(150deg, var(--pw-bg-surface) 35%, color-mix(in srgb, var(--pw-ai-mesh-b) 9%, var(--pw-bg-surface)) 100%);
}
.pw-glance-mark--lg { --pw-glance-mark-size: 44px; --pw-mark-radius: var(--pw-radius-lg); }
.pw-glance-mark--xl { --pw-glance-mark-size: 96px; --pw-mark-radius: var(--pw-radius-3xl); }

/* Waiting is a ring outside the body, concentric with it. The ring is the
   signal; its slow breath is the only loop CSS owns here, and under reduced
   motion the ring simply stays. */
.pw-orb::after, .pw-glance-mark::after {
  content: ""; position: absolute; inset: -3px;
  border-radius: calc(var(--pw-mark-radius) + 3px);
  border: 1.5px solid currentColor;
  opacity: 0; transform: scale(.92);
  transition: opacity var(--pw-duration-base) var(--pw-ease-out), transform var(--pw-duration-base) var(--pw-ease-out);
  pointer-events: none;
}
.pw-orb[data-state="waiting"]::after { opacity: .55; transform: scale(1); animation: pw-mark-wait 2.4s ease-in-out infinite; }
@keyframes pw-mark-wait { 50% { opacity: .2; transform: scale(1.06); } }

/* Error: the body and the dots both turn, and it shakes once on arrival. The
   animation restarts only when the state is newly set, so a failed answer
   that stays on screen is still, not twitching. */
.pw-orb[data-state="error"], .pw-glance-mark[data-state="error"] {
  color: var(--pw-tint-danger-fg);
  animation: pw-mark-shake 420ms var(--pw-ease-out) 1;
}
.pw-orb[data-state="error"] {
  background: radial-gradient(circle at 34% 28%,
    var(--pw-tint-danger-bg) 0%, var(--pw-tint-danger-bg) 45%,
    color-mix(in srgb, currentColor 14%, var(--pw-tint-danger-bg)) 100%);
}
.pw-glance-mark[data-state="error"] {
  background: linear-gradient(150deg,
    var(--pw-tint-danger-bg) 35%,
    color-mix(in srgb, currentColor 10%, var(--pw-tint-danger-bg)) 100%);
}
@keyframes pw-mark-shake {
  20% { transform: translateX(-2px); }
  40% { transform: translateX(2px); }
  60% { transform: translateX(-1px); }
  80% { transform: translateX(1px); }
}

/* -- Versions, and saying it again -------------------------------------------
   Regenerating an answer used to throw the old one away. Now every answer a
   turn has had is kept, and a pager -- "2 / 3" -- moves between them: the
   reader may prefer the first, and a tool that discards it on a second press
   punishes them for asking. The same for the person's own words: editing a
   message keeps what was said before as a version, so the conversation that
   followed the old wording is still there to go back to.

   A version is a `.pw-msg__version` in the body; the one not hidden is shown.
   Appending one makes it the newest and the current. */
.pw-msg__version[hidden] { display: none; }
.pw-versions { display: inline-flex; align-items: center; gap: var(--pw-space-1); height: 32px; }
/* Small arrows: the pager is a reading aid beside the answer's tools, not one
   of them, so it sits a size below Copy and Regenerate. */
.pw-versions .pw-versions__arrow { --pw-btn-height: 24px; width: 24px; border-radius: var(--pw-radius-circle); }
.pw-versions .pw-versions__arrow .pw-icon { width: 14px; height: 14px; }
/* Up to three versions: steps. A dot each, the current one long. */
.pw-versions__steps { display: inline-flex; align-items: center; gap: 4px; padding-inline: var(--pw-space-1); }
.pw-versions__steps[hidden] { display: none; }
.pw-versions__step {
  width: 6px; height: 6px; border-radius: var(--pw-radius-pill);
  background: var(--pw-fg-quaternary);
}
.pw-versions__step.is-current { background: var(--pw-fg-secondary); }
/* Past three: the count. */
.pw-versions__count {
  min-width: 36px; text-align: center;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums;
}

/* The person's message, with its tools under the bubble. The pager is always
   there when there is more than one version -- it is information. Edit shows on
   hover or focus, and always on touch, where there is no hover to ask. */
.pw-msg--user.has-tools { flex-direction: column; align-items: flex-end; gap: var(--pw-space-2); }
.pw-msg__tools { display: flex; align-items: center; gap: var(--pw-space-2); }
.pw-msg__tools [data-pw-edit] { opacity: 0; transition: opacity var(--pw-duration-fast) var(--pw-ease-out); }
.pw-msg--user:is(:hover, :focus-within) .pw-msg__tools [data-pw-edit] { opacity: 1; }
@media (hover: none) { .pw-msg__tools [data-pw-edit] { opacity: 1; } }

/* Editing: the bubble becomes the field, in place and at the bubble's width,
   so the words being changed stay where the reader last saw them. */
.pw-msg__editor { display: flex; flex-direction: column; gap: var(--pw-space-4); width: min(100%, 520px); }
.pw-msg__editor-actions { display: flex; justify-content: flex-end; gap: var(--pw-space-3); }
.pw-msg--user.is-editing > .pw-msg__body,
.pw-msg--user.is-editing .pw-msg__tools { display: none; }

/* -- Saying an answer was wrong ----------------------------------------------
   Thumbs up records and is done. Thumbs down opens a short panel under the
   answer -- not a modal: the answer it is about stays in view while the
   reader says what was wrong with it. A few reasons as chips, an optional
   note, and one choice about what is shared.

   Sharing the whole conversation is OFF by default and says so. The panel
   states exactly what Send sends -- this answer, its question and what was
   chosen here -- and changes the sentence when the switch is on, because a
   privacy product that is vague about what a feedback button sends is the
   thing it exists to not be. */
.pw-msg__actions [data-pw-feedback][aria-pressed="true"],
.pw-glance__foot [data-pw-feedback][aria-pressed="true"] { background: var(--pw-bg-selected); color: var(--pw-fg-brand); }
.pw-feedback {
  display: flex; flex-direction: column; gap: var(--pw-space-5);
  margin-block-start: var(--pw-space-5);
  padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-feedback__title {
  margin: 0;
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-feedback__reasons { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); }
.pw-feedback__share {
  display: flex; align-items: center; gap: var(--pw-space-4);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary);
}
.pw-feedback__note {
  margin: calc(var(--pw-space-3) * -1) 0 0;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
}
.pw-feedback__actions { display: flex; align-items: center; gap: var(--pw-space-3); }
/* Sent: one line, where the panel was. */
.pw-feedback.is-sent {
  flex-direction: row; align-items: center; gap: var(--pw-space-3);
  padding: var(--pw-space-4) var(--pw-space-6);
  background: var(--pw-skeleton-base);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary);
}
.pw-feedback.is-sent > :not(.pw-feedback__done) { display: none; }
.pw-feedback__done { display: none; align-items: center; gap: var(--pw-space-3); }
.pw-feedback.is-sent > .pw-feedback__done { display: flex; }
.pw-feedback__done .pw-icon { color: var(--pw-fg-success); }

/* -- Temporary chat -----------------------------------------------------------
   The mode a privacy product is most expected to have. Turned on from the
   header of a new chat; while it is on, three things say so at once -- the
   toggle filled in the inverse colour, a banner at the top of the thread
   saying what temporary means, and a dashed composer -- because a mode that
   changes what happens to your words must never be mistaken for the normal
   one at a glance. Ending it with messages in the thread asks first: the
   banner turns into the question, in place. */
.pw-temp-toggle[aria-pressed="true"] {
  background: var(--pw-fg-primary); border-color: var(--pw-fg-primary);
  color: var(--pw-bg-surface);
}
.pw-temp-toggle[aria-pressed="true"]:hover { background: var(--pw-fg-secondary); border-color: var(--pw-fg-secondary); }
.pw-temp-banner {
  display: none; align-items: flex-start; gap: var(--pw-space-5);
  margin-block-end: var(--pw-space-10);
  padding: var(--pw-space-6) var(--pw-space-7);
  border: 1px dashed var(--pw-border-strong);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-skeleton-base);
}
[data-pw-temporary] .pw-temp-banner { display: flex; }
.pw-temp-banner__icon {
  display: grid; place-items: center; flex: none;
  width: 32px; height: 32px;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-fg-primary); color: var(--pw-bg-surface);
}
.pw-temp-banner__body { display: flex; flex-direction: column; gap: var(--pw-space-1); min-width: 0; flex: 1; }
.pw-temp-banner__title {
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-temp-banner__text { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-temp-banner__confirm { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); margin-block-start: var(--pw-space-4); }
.pw-temp-banner__confirm[hidden] { display: none; }
[data-pw-temporary] .pw-composer { border-style: dashed; }

/* -- What the assistant remembers ---------------------------------------------
   Memory is the assistant keeping something from one chat for the next. It
   is only acceptable if it is visible and reversible everywhere it happens:

     .pw-memory         the list, in settings: every fact, where it came from,
                        a Forget on each, and a switch that stops it all.
     .pw-memory-used    on an answer that leaned on a memory -- which ones, and
                        the way to forget them without leaving the answer.
     .pw-memory-saved   the moment something is kept: said once, with Undo.

   Nothing is remembered silently, and nothing remembered is used silently. */
.pw-memory { display: flex; flex-direction: column; gap: var(--pw-space-6); }
.pw-memory__head { display: flex; align-items: flex-start; gap: var(--pw-space-6); }
.pw-memory__title {
  margin: 0;
  font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line);
  font-weight: var(--pw-font-weight-bold); color: var(--pw-fg-primary);
}
.pw-memory__desc { margin: var(--pw-space-1) 0 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-tertiary); }
.pw-memory__head .pw-switch { margin-inline-start: auto; flex: none; }
.pw-memory__list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-lg); }
.pw-memory__item { display: flex; align-items: center; gap: var(--pw-space-5); padding: var(--pw-space-5) var(--pw-space-5) var(--pw-space-5) var(--pw-space-7); }
.pw-memory__item + .pw-memory__item { border-top: 1px solid var(--pw-border-subtle); }
.pw-memory__fact { display: flex; flex-direction: column; gap: var(--pw-space-1); min-width: 0; flex: 1; }
.pw-memory__text { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-primary); }
.pw-memory__from { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-memory__from a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.pw-memory__empty { padding: var(--pw-space-8); text-align: center; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); }
.pw-memory__empty[hidden] { display: none; }
.pw-memory__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-3); }
.pw-memory__foot-note { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
/* Off: kept, but not used and not added to -- the list dims to say so, and
   stays editable, because turning memory off is not the same as forgetting. */
.pw-memory.is-off .pw-memory__list { opacity: .55; }
.pw-memory__off-note { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-memory:not(.is-off) .pw-memory__off-note { display: none; }

/* On an answer: a quiet chip above it. It names a count, and opens the list of
   exactly which memories shaped this answer. */
.pw-memory-used {
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  margin-block-end: var(--pw-space-4);
  padding: var(--pw-space-1) var(--pw-space-4);
  border: 0; border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-muted);
  font: inherit; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  color: var(--pw-fg-secondary); cursor: pointer;
}
.pw-memory-used:hover, .pw-memory-used[aria-expanded="true"] { background: var(--pw-bg-active); color: var(--pw-fg-primary); }
.pw-memory-used .pw-icon { color: var(--pw-tint-ai-fg); }
.pw-memory-pop { padding: var(--pw-space-4); }
.pw-memory-pop__title { margin: 0; padding: var(--pw-space-2) var(--pw-space-3) var(--pw-space-3); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary); }
.pw-memory-pop .pw-memory__item { padding: var(--pw-space-3); border: 0; }
.pw-memory-pop__foot { padding: var(--pw-space-3) var(--pw-space-3) var(--pw-space-1); border-top: 1px solid var(--pw-border-subtle); margin-top: var(--pw-space-2); }

/* The moment something is kept. */
.pw-memory-saved {
  display: flex; align-items: center; gap: var(--pw-space-3);
  margin-block-start: var(--pw-space-4);
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
}
.pw-memory-saved .pw-icon { color: var(--pw-tint-ai-fg); flex: none; }
.pw-memory-saved__text { min-width: 0; }
.pw-memory-saved strong { color: var(--pw-fg-secondary); font-weight: var(--pw-font-weight-semibold); }

/* -- Choosing not to see Glance ---------------------------------------------
   Not wanting a machine's answer above your results is a reasonable choice,
   and a product that does not manipulate makes it an easy one. Three modes --
   Automatic, On Request, Off -- and topics that can be left out of Glance even
   when it is on. On Request and a left-out topic show an OFFER in the
   Glance's place: one slim row, the mark at rest, and a button. Off shows
   nothing at all, and never asks again. */
.pw-glance-settings { display: flex; flex-direction: column; gap: var(--pw-space-7); }
.pw-glance-settings__row { display: flex; flex-direction: column; gap: var(--pw-space-4); }
/* A choice of three is as wide as its words, not the card: stretched, the
   segments float in empty track and read as a progress bar. */
.pw-glance-settings__row > .pw-segmented { align-self: flex-start; }
.pw-glance-settings__label { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-glance-settings__hint { margin: calc(var(--pw-space-2) * -1) 0 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-glance-settings__topics { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); }
/* With Glance off, topics have nothing to leave out of. */
.pw-glance-settings.is-off [data-pw-glance-topics] { opacity: .5; pointer-events: none; }

.pw-glance-offer {
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-4) var(--pw-space-4) var(--pw-space-4) var(--pw-space-5);
  border: 1px dashed var(--pw-ai-edge-b);
  border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
}
.pw-glance-offer__text { flex: 1; min-width: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-glance-offer__text strong { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }

/* -- Voice ---------------------------------------------------------------------
   Talking instead of typing. The orb fills the panel and is the whole of the
   interface: it LISTENS (dots catch the incoming voice, harder the louder it
   is), THINKS, and SPEAKS (bands of light roll across it). Captions under it
   carry the words -- yours, quieter, while you speak; the answer's while it
   is spoken -- so nothing depends on hearing or on the motion. Three round
   controls: mute, end, type instead. Muted is shown by the button, filled,
   and by the orb going still. */
.pw-voice {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column; align-items: center;
  padding: var(--pw-space-12) var(--pw-space-8) var(--pw-space-10);
  background:
    radial-gradient(60% 50% at 50% 38%, var(--pw-ai-glow-b), transparent 70%),
    radial-gradient(50% 40% at 30% 72%, var(--pw-ai-glow-a), transparent 70%),
    var(--pw-bg-surface);
}
.pw-voice[hidden] { display: none; }
.pw-voice__stage {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--pw-space-12); width: 100%;
}
.pw-voice__caption {
  max-width: 440px; min-height: calc(var(--pw-text-lg-line) * 3); margin: 0;
  text-align: center;
  font-size: var(--pw-text-lg-size); line-height: var(--pw-text-lg-line);
  color: var(--pw-fg-primary);
}
.pw-voice__caption[data-speaker="you"] { color: var(--pw-fg-tertiary); }
.pw-voice__controls { display: flex; align-items: center; gap: var(--pw-space-8); }
.pw-voice__btn {
  display: grid; place-items: center;
  width: 52px; height: 52px;
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-circle);
  background: var(--pw-bg-surface); color: var(--pw-fg-primary);
  box-shadow: var(--pw-shadow-sm);
  cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-voice__btn:hover { background: var(--pw-bg-hover); }
.pw-voice__btn[aria-pressed="true"] { background: var(--pw-fg-primary); border-color: var(--pw-fg-primary); color: var(--pw-bg-surface); }
.pw-voice__btn--end { width: 60px; height: 60px; border: 0; background: var(--pw-color-danger-600); color: var(--pw-color-white); }
.pw-voice__btn--end:hover { background: var(--pw-color-danger-700); }

/* -- Deep research -------------------------------------------------------------
   A long task done in the open. It PROPOSES a plan before spending the time
   -- the steps it means to take, Start Research, Edit Plan -- so the scope is
   agreed rather than discovered. RUNNING, every step says whether it is done,
   under way or waiting, the step under way names what it is reading, and the
   source count climbs. There is no percentage: none of this is measurable, and
   a bar that lies is worse than a list that does not. DONE, it hands over a
   report; STOPPED, it hands over what it had.

   State is `data-state` on `.pw-research`; a step is done, active or pending
   by its `data-status`. The card is interface -- its counts change every frame
   -- so it sits outside the word reveal; the report arrives like any answer. */
.pw-research {
  display: flex; flex-direction: column; gap: var(--pw-space-6);
  margin-block: var(--pw-space-2) var(--pw-space-5);
  padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-research__title {
  margin: 0;
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-research__meta {
  margin: var(--pw-space-1) 0 0;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
  font-variant-numeric: tabular-nums;
}
.pw-research__plan { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.pw-research__step {
  position: relative;
  display: grid; grid-template-columns: 20px 1fr; column-gap: var(--pw-space-5);
  padding-bottom: var(--pw-space-6);
  /* The row's line is the circle's height, so the first line of the step
     shares the circle's centre. Inherited from an answer, the line was 28px
     and the words sat 4px below the circle beside them. */
  font-size: var(--pw-text-sm-size); line-height: 20px;
}
.pw-research__step:last-child { padding-bottom: 0; }
.pw-research__step:not(:last-child)::after {
  content: ""; position: absolute; inset-inline-start: 9.5px; top: 24px; bottom: 4px;
  width: 1px; background: var(--pw-border-subtle);
}
.pw-research__mark {
  display: grid; place-items: center;
  width: 20px; height: 20px;
  border: 1.5px solid var(--pw-border-strong);
  border-radius: var(--pw-radius-circle);
  color: var(--pw-bg-surface);
}
.pw-research__mark .pw-icon, .pw-research__mark .pw-spinner { display: none; }
.pw-research__step[data-status="done"] .pw-research__mark { border-color: var(--pw-fg-success); background: var(--pw-fg-success); }
.pw-research__step[data-status="done"] .pw-research__mark .pw-icon { display: block; }
.pw-research__step[data-status="active"] .pw-research__mark { border-color: transparent; }
.pw-research__step[data-status="active"] .pw-research__mark .pw-spinner { display: block; }
.pw-research__step-title { font-size: var(--pw-text-sm-size); line-height: 20px; color: var(--pw-fg-primary); }
.pw-research__step[data-status="pending"] .pw-research__step-title { color: var(--pw-fg-tertiary); }
.pw-research__step-detail { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-research__now { display: none; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); }
.pw-research__step[data-status="active"] .pw-research__now { display: block; }
.pw-research__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-3); }
.pw-research__note { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
/* What the foot offers depends on where the research is. */
.pw-research[data-state="proposed"] [data-pw-when]:not([data-pw-when~="proposed"]),
.pw-research[data-state="running"]  [data-pw-when]:not([data-pw-when~="running"]),
.pw-research[data-state="done"]     [data-pw-when]:not([data-pw-when~="done"]),
.pw-research[data-state="stopped"]  [data-pw-when]:not([data-pw-when~="stopped"]) { display: none; }
.pw-research[data-state="editing"]  [data-pw-when]:not([data-pw-when~="editing"]) { display: none; }
/* Editing the plan: numbered fields, each with move and remove. */
.pw-research__editrow { display: flex; align-items: center; gap: var(--pw-space-3); padding-block: var(--pw-space-2); }
.pw-research__editnum { flex: none; display: grid; place-items: center; width: 20px; height: 20px; border-radius: var(--pw-radius-circle); background: var(--pw-bg-muted); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-secondary); }
.pw-research__editrow .pw-input-wrap { flex: 1 1 auto; min-width: 0; }
.pw-research__addrow { padding-block: var(--pw-space-2); padding-inline-start: calc(20px + var(--pw-space-3) - var(--pw-space-4)); }

/* The report: a document inside the answer -- what was found, in sections the
   reader can jump between, with every claim cited and every source listed. */
.pw-report {
  display: flex; flex-direction: column; gap: var(--pw-space-5);
  padding: var(--pw-space-8);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-report__kicker { margin: 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-tint-ai-fg); }
.pw-report__title { margin: 0; font-size: var(--pw-text-lg-size); line-height: var(--pw-text-lg-line); font-weight: var(--pw-font-weight-bold); color: var(--pw-fg-primary); }
.pw-report__meta { margin: calc(var(--pw-space-3) * -1) 0 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-report__toc { margin: 0; padding: var(--pw-space-5) var(--pw-space-6); padding-inline-start: calc(var(--pw-space-6) + 1.2em); border-radius: var(--pw-radius-md); background: var(--pw-bg-subtle); }
.pw-report__toc li { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-md-line); }
.pw-report__toc a { color: var(--pw-fg-secondary); text-decoration: none; }
.pw-report__toc a:hover { color: var(--pw-fg-primary); text-decoration: underline; }
.pw-report__section { scroll-margin-top: var(--pw-space-12); }
.pw-report__section h4 { margin: 0 0 var(--pw-space-2); font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-report__section p { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-lg-line); color: var(--pw-fg-secondary); }
.pw-report__actions { display: flex; gap: var(--pw-space-3); }

/* -- Sharing and exporting a chat -------------------------------------------
   Sharing turns a private conversation into something other people can read,
   so the dialog is honest about exactly that before the link exists: a copy
   of the chat as it is now, readable by anyone who has the link. Your name and
   the files you added are OFF by default, and a note asks the reader to look
   it over for anything personal -- the one moment that check is worth making.
   Once made, the link sits in a field with Copy, and can be deleted.

   Export is a small panel, not a dialog: a format, whether to keep the sources,
   and Download. Nothing about exporting to your own disk needs a warning. */
.pw-share { display: flex; flex-direction: column; gap: var(--pw-space-7); }
/* Hide what does not belong to the state; leave what does exactly as its own
   rule lays it out. (Showing with `display: revert` dropped these back to the
   browser's defaults and undid every flex layout in the dialog.) */
.pw-share[data-state="draft"]  [data-pw-when]:not([data-pw-when~="draft"]),
.pw-share[data-state="shared"] [data-pw-when]:not([data-pw-when~="shared"]) { display: none; }
/* The dialog's footer sits outside the body, in its own padding like every
   modal's, and follows the same state from there. */
.pw-modal:has(.pw-share[data-state="draft"])  .pw-modal__footer [data-pw-when]:not([data-pw-when~="draft"]),
.pw-modal:has(.pw-share[data-state="shared"]) .pw-modal__footer [data-pw-when]:not([data-pw-when~="shared"]) { display: none; }
.pw-share__preview {
  display: flex; flex-direction: column; gap: var(--pw-space-2);
  padding: var(--pw-space-6) var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-skeleton-base);
}
.pw-share__preview-title { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-share__preview-meta { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-share__preview-quote {
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pw-share__options { display: flex; flex-direction: column; gap: var(--pw-space-5); }
.pw-share__option { display: flex; align-items: center; gap: var(--pw-space-5); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-primary); }
.pw-share__option .pw-switch { margin-inline-start: auto; flex: none; }
.pw-share__check {
  display: flex; gap: var(--pw-space-4);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary);
}
.pw-share__check .pw-icon { flex: none; margin-top: 2px; color: var(--pw-fg-warning); }
.pw-share__link { display: flex; align-items: center; gap: var(--pw-space-3); }
.pw-share__link .pw-input-wrap { flex: 1; min-width: 0; }
.pw-share__note { margin: 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }

.pw-export { width: 300px; padding: var(--pw-space-7); display: flex; flex-direction: column; gap: var(--pw-space-6); }
.pw-export__title { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-export .pw-segmented { align-self: flex-start; }
.pw-export__option { display: flex; align-items: center; gap: var(--pw-space-5); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-primary); }
.pw-export__option .pw-switch { margin-inline-start: auto; flex: none; }

/* -- Two drafts, pick one ------------------------------------------------------
   When there are two good ways to say something, the assistant can offer both
   and let the reader choose -- side by side, because comparing is the whole
   task and scrolling between them makes it a memory test. Each draft carries
   a short note on how it differs ("Shorter, more direct"), so the reader
   knows what to look for. Picking keeps the chosen one as the answer and
   folds the other to a line that can bring the comparison back; Neither
   Works asks for another pair. Side by side while there is room, stacked
   when not. */
.pw-drafts { display: flex; flex-direction: column; gap: var(--pw-space-5); margin-block: var(--pw-space-2) var(--pw-space-4); }
.pw-drafts__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--pw-space-5); }
.pw-drafts__option {
  display: flex; flex-direction: column; gap: var(--pw-space-5);
  padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  transition: border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-drafts__option:hover { border-color: var(--pw-border-default); }
.pw-drafts__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--pw-space-2) var(--pw-space-4); }
.pw-drafts__label {
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  font-weight: var(--pw-font-weight-bold); color: var(--pw-tint-ai-fg);
  text-transform: uppercase; letter-spacing: .04em;
}
.pw-drafts__note { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-drafts__body { flex: 1; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-lg-line); color: var(--pw-fg-secondary); }
.pw-drafts__body > * { margin: 0; }
.pw-drafts__body > * + * { margin-top: var(--pw-space-4); }
.pw-drafts__option > .pw-btn { align-self: flex-start; }
.pw-drafts__foot { display: flex; align-items: center; gap: var(--pw-space-3); }
/* Picked: the chosen draft is the answer, at full width, without its button;
   the other is one line. */
/* The box is the ghosts' frame during the pick. */
.pw-drafts { position: relative; }
.pw-drafts__ghost { z-index: 1; }
.pw-drafts.is-picked .pw-drafts__grid { grid-template-columns: 1fr; }
.pw-drafts.is-picked .pw-drafts__option:not(.is-chosen) { display: none; }
.pw-drafts.is-picked .pw-drafts__option.is-chosen > .pw-btn { display: none; }
.pw-drafts.is-picked .pw-drafts__option.is-chosen { border-color: var(--pw-border-strong); }
.pw-drafts__aside { display: none; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-drafts.is-picked .pw-drafts__aside { display: flex; }
.pw-drafts.is-picked .pw-drafts__foot { display: none; }

/* -- A draft you can mark up ---------------------------------------------------
   A longer draft -- a letter, a plan, a page -- arrives in the chat as a card
   (.pw-doccard) and opens as a page of its own (.pw-doc), because a document
   is read and judged as a whole, not in a bubble. There, the reader marks it
   up the way people mark up paper: select words, add a note. Each note
   numbers its passage in the page and sits in the margin beside it, and
   Revise sends every passage with its note, so the assistant changes what was
   pointed at and nothing else. What it changed comes back marked.

   Selecting text is not open to everyone, so the margin also takes a General
   Note that points at nothing in particular. */
.pw-doccard {
  display: flex; align-items: center; gap: var(--pw-space-6);
  width: 100%; margin-block: var(--pw-space-2) var(--pw-space-4);
  padding: var(--pw-space-6) var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  font: inherit; text-align: start; color: inherit; cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-doccard:hover { background: var(--pw-bg-hover); border-color: var(--pw-border-default); }
.pw-doccard__body { display: flex; flex-direction: column; gap: var(--pw-space-1); min-width: 0; flex: 1; }
.pw-doccard__title { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-doccard__meta { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-doccard__excerpt {
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pw-doccard > .pw-icon { flex: none; color: var(--pw-fg-quaternary); }

.pw-doc {
  position: fixed; inset: 0; z-index: var(--pw-z-modal);
  display: flex; flex-direction: column;
  /* One white sheet, edge to edge: the draft is the only thing on it, in a
     reading column down the middle. No card, no grey desk around it. */
  background: var(--pw-bg-surface);
}
.pw-doc[hidden] { display: none; }
.pw-doc__bar {
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-5) var(--pw-space-8);
  border-bottom: 1px solid var(--pw-border-subtle);
  background: var(--pw-bg-surface);
}
.pw-doc__heading { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.pw-doc__title { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-doc__meta { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-doc__main { flex: 1; min-height: 0; overflow-y: auto; padding: var(--pw-space-16) var(--pw-space-8) calc(var(--pw-space-16) * 3); }
.pw-doc__page {
  max-width: 660px; margin-inline: auto;
  font-size: var(--pw-text-md-size); line-height: 30px; color: var(--pw-fg-primary);
}
.pw-doc__page > * { margin: 0; }
.pw-doc__page > * + * { margin-top: var(--pw-space-8); }
.pw-doc__page ::selection { background: color-mix(in srgb, var(--pw-tint-ai-fg) 24%, transparent); }
.pw-doc[data-state="revising"] .pw-doc__page { pointer-events: none; }
/* About to change: the passage glows, breathing on --pw-pending (0 to 1,
   driven by GSAP), so the reader sees exactly what the revision will touch. */
.pw-annot.is-pending {
  --pw-pending: 0;
  background: color-mix(in srgb, var(--pw-tint-ai-fg) calc(14% + var(--pw-pending) * 20%), transparent);
  box-shadow: 0 0 calc(4px + var(--pw-pending) * 10px) color-mix(in srgb, var(--pw-tint-ai-fg) calc(20% + var(--pw-pending) * 25%), transparent);
}
/* Turning to smoke: the highlight lets go of the words it held. */
.pw-annot.is-smoke { background: none; border-bottom-color: transparent; box-shadow: none; }
.pw-annot.is-smoke::after { display: none; }
.pw-smoke { display: inline-block; white-space: pre; }

/* A passage with a note: tinted, underlined in the AI colour, and numbered so
   it can be found from the margin and the margin from it. */
.pw-annot {
  background: color-mix(in srgb, var(--pw-tint-ai-fg) 12%, transparent);
  border-bottom: 2px solid var(--pw-tint-ai-fg);
  border-radius: 2px;
  color: inherit; cursor: pointer;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
.pw-annot::after {
  content: attr(data-pw-note);
  display: inline-grid; place-items: center; min-width: 16px; height: 16px;
  margin-inline-start: 2px; padding-inline: 3px; vertical-align: 3px;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-tint-ai-fg); color: var(--pw-bg-surface);
  font-size: 10px; line-height: 1; font-weight: var(--pw-font-weight-bold);
}
.pw-annot.is-active { background: color-mix(in srgb, var(--pw-tint-ai-fg) 26%, transparent); }
.pw-annot:focus-visible { outline: 2px solid var(--pw-tint-ai-fg); outline-offset: 2px; }
/* What the revision changed: marked until the reader has seen it. */
.pw-doc__changed { background: var(--pw-tint-success-bg); color: var(--pw-tint-success-fg); border-radius: 2px; -webkit-box-decoration-break: clone; box-decoration-break: clone; }

.pw-doc__add {
  position: fixed; z-index: var(--pw-z-popover);
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  box-shadow: var(--pw-shadow-lg);
}
.pw-doc__add[hidden] { display: none; }

/* Notes float over the sheet rather than taking a column from it. A note on
   a passage is anchored to that passage -- it opens under the words it is
   about and follows them as the page scrolls. General notes, about the whole
   draft, stack in a floating card on the right. */
.pw-doc__float {
  position: absolute; z-index: 2;
  top: calc(var(--pw-space-16) + 56px); inset-inline-end: var(--pw-space-8);
  width: 300px; max-height: calc(100% - 140px); overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--pw-space-4);
}
.pw-doc__float[hidden] { display: none; }
.pw-note--anchored { position: fixed; z-index: var(--pw-z-popover); width: 320px; }
.pw-note--anchored[hidden] { display: none; }
.pw-doc__hint {
  position: absolute; inset-block-end: var(--pw-space-10); left: 50%; translate: -50% 0;
  padding: var(--pw-space-3) var(--pw-space-7);
  border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-inverse); color: var(--pw-fg-inverse);
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  box-shadow: var(--pw-shadow-lg); pointer-events: none;
}
.pw-doc__hint[hidden] { display: none; }
.pw-note {
  display: flex; flex-direction: column; gap: var(--pw-space-4);
  padding: var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  box-shadow: var(--pw-shadow-lg);
  transition: border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-note.is-active { border-color: var(--pw-tint-ai-fg); }
.pw-note__head { display: flex; align-items: center; gap: var(--pw-space-3); }
.pw-note__num {
  display: inline-grid; place-items: center; flex: none; min-width: 18px; height: 18px; padding-inline: 4px;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-tint-ai-fg); color: var(--pw-bg-surface);
  font-size: 10px; line-height: 1; font-weight: var(--pw-font-weight-bold);
}
.pw-note__quote {
  flex: 1; min-width: 0; margin: 0;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pw-note__text { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-primary); white-space: pre-wrap; }
.pw-note__actions { display: flex; gap: var(--pw-space-2); justify-content: flex-end; }
@media (max-width: 900px) {
  .pw-doc__float { inset-inline: var(--pw-space-5); width: auto; top: auto; inset-block-end: var(--pw-space-5); max-height: 50%; }
}

/* -- An answer with a map ------------------------------------------------------
   When the answer is places, the map is part of the answer: suggested spots
   pinned where they are, your position among them, and the places themselves
   as a rail of cards along the map's foot -- photo, name, rating and kind,
   price, and whether it is open. Pins carry the rating, because that is what
   a reader compares across a map. A card and its pin are one thing: choosing
   either selects both, and the rail scrolls to the card when a pin is chosen.

   It sits inside an assistant message like any block, and on the Maps search
   surface as the answer to "what's nearby". Chat and Maps only -- never in a
   Glance. */
.pw-amap {
  position: relative;
  margin-block: var(--pw-space-2) var(--pw-space-5);
  border-radius: var(--pw-radius-xl);
  overflow: hidden;
  background-image: var(--pw-map-tile), var(--pw-map-tile-fallback);
  background-size: cover; background-position: center;
  box-shadow: inset 0 0 0 1px var(--pw-border-subtle);
}
.pw-amap__map { position: relative; height: 340px; }
.pw-amap--tall .pw-amap__map { height: 460px; }
.pw-amap__map > * { position: absolute; }
.pw-amap__pin {
  translate: -50% -100%;
  display: inline-flex; align-items: center; gap: var(--pw-space-1);
  height: 26px; padding: 0 var(--pw-space-4);
  border: 0; border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-surface); color: var(--pw-fg-primary);
  box-shadow: var(--pw-shadow-md);
  font: inherit; font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-bold);
  font-variant-numeric: tabular-nums; cursor: pointer;
  transition: scale var(--pw-duration-fast) var(--pw-ease-out), background-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-amap__pin .pw-icon { color: var(--pw-fg-warning); }
.pw-amap__pin:hover { scale: 1.08; }
/* A ring for the keyboard, not for a click: pressing a pin with the mouse
   already says which one was chosen. */
.pw-amap__pin:focus { outline: none; }
.pw-amap__pin:focus-visible { outline: 2px solid var(--pw-fg-brand); outline-offset: 2px; }
.pw-amap__pin.is-selected { z-index: 2; scale: 1.15; background: var(--pw-fg-primary); color: var(--pw-bg-surface); }
.pw-amap__pin.is-selected .pw-icon { color: inherit; }
.pw-amap__area {
  translate: -50% -50%;
  font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-bold);
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--pw-fg-tertiary); pointer-events: none;
}
.pw-amap__rail-wrap { position: absolute; inset-inline: 0; inset-block-end: 0; }
.pw-amap__rail {
  display: flex; gap: var(--pw-space-4);
  padding: var(--pw-space-5);
  overflow-x: auto; scroll-behavior: smooth; scrollbar-width: none;
  scroll-snap-type: x mandatory;
  /* Snapping must know about the padding, or it snaps the first card to the
     very edge -- scrolling the rail by the padding, which the edge scroller
     then reads as "more to the left" and fades a card nothing is behind. */
  scroll-padding-inline: var(--pw-space-5);
}
.pw-amap__rail::-webkit-scrollbar { display: none; }
.pw-amap__rail.has-lead  { --pw-fade-lead: 40px; }
.pw-amap__rail.has-trail { --pw-fade-trail: 40px; }
.pw-amap__place {
  flex: 0 0 auto; width: 300px; scroll-snap-align: start;
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-4);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
  font: inherit; text-align: start; color: inherit; cursor: pointer;
  transition: border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-amap__place.is-selected { border-color: var(--pw-fg-primary); }
/* Cards in an answer are flat -- a hairline, no shadow; the page they sit on
   is the answer. Only the rail that floats over the map lifts its cards, so
   they read against the tiles. */
.pw-amap__rail-wrap .pw-amap__place { box-shadow: var(--pw-shadow-lg); }
.pw-amap__photo { flex: none; width: 64px; height: 64px; border-radius: var(--pw-radius-md); object-fit: cover; background: var(--pw-bg-muted); }
.pw-amap__body { display: flex; flex-direction: column; gap: var(--pw-space-1); min-width: 0; }
.pw-amap__name {
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pw-amap__meta { display: flex; align-items: center; gap: var(--pw-space-2); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); white-space: nowrap; }
.pw-amap__meta .pw-icon { color: var(--pw-fg-warning); }
.pw-amap__open { color: var(--pw-fg-success); }
.pw-amap__closed { color: var(--pw-fg-danger); }
.pw-amap__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 28px; height: 28px;
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-circle);
  background: var(--pw-bg-surface); color: var(--pw-fg-secondary);
  box-shadow: var(--pw-shadow-md); cursor: pointer;
}
.pw-amap__nav--next { inset-inline-end: var(--pw-space-3); }
.pw-amap__nav--prev { inset-inline-start: var(--pw-space-3); }
[dir="rtl"] .pw-amap__nav svg { transform: scaleX(-1); }

/* -- Maps search: ask what is nearby --------------------------------------------
   Maps with the assistant as its search box. A title, an AI composer that asks
   rather than searches ("Ask what's nearby"), the answer map under it, and
   below that IDEAS: things worth doing near here, as photographs with a line
   each. An idea is a question already written -- pressing it asks it -- so
   the page offers somewhere to start without asking the reader to know what
   to type. The answer lands between the composer and the map, the map picks
   out the places it names. */
/* The same column as a project: 768 wide, centred, title centred over it. */
.pw-mapsearch { display: flex; flex-direction: column; gap: var(--pw-space-10); max-width: 768px; margin-inline: auto; }
.pw-mapsearch__head { position: relative; display: flex; align-items: center; justify-content: center; min-height: 32px; }
.pw-mapsearch__head > .pw-btn, .pw-mapsearch__menu { position: absolute; inset-inline-end: 0; }
.pw-mapsearch__title { margin: 0; font-size: var(--pw-text-xl-size); line-height: var(--pw-text-xl-line); font-weight: var(--pw-font-weight-bold); color: var(--pw-fg-primary); text-align: center; }
.pw-mapsearch__answer { display: flex; gap: var(--pw-space-5); }
.pw-mapsearch__answer[hidden] { display: none; }
.pw-mapsearch__answer .pw-msg__body { font-size: var(--pw-text-md-size); line-height: var(--pw-text-lg-line); color: var(--pw-fg-secondary); }
.pw-mapsearch .pw-amap { margin: 0; }

.pw-ideas { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--pw-space-6); }
.pw-idea {
  position: relative; aspect-ratio: 3 / 4; overflow: hidden;
  padding: 0; border: 0; border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-muted);
  font: inherit; text-align: start; color: var(--pw-color-white); cursor: pointer;
}
.pw-idea img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: scale var(--pw-duration-slow) var(--pw-ease-out); }
.pw-idea:hover img { scale: 1.04; }
/* The line sits on its own scrim, so it reads on any photograph. */
.pw-idea__text {
  position: absolute; inset-inline: 0; inset-block-end: 0;
  padding: var(--pw-space-16) var(--pw-space-7) var(--pw-space-7);
  /* The lightbox wash: dark in both themes, which is what text on a photo needs. */
  background: linear-gradient(to top, var(--pw-bg-lightbox), transparent);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold);
}

/* -- A question opened as its own conversation ---------------------------------
   An idea pressed on Maps opens a whole page, not an answer squeezed between
   the composer and the map: a bar with Back and the idea's line, the thread in
   the same 768 column as every chat, the question first with the photograph
   it came from, the answer under it, and the composer docked at the bottom for
   the follow-up. It covers the page it came from, and Back returns to it. */
.pw-chatpage {
  position: fixed; inset: 0; z-index: var(--pw-z-sheet);
  display: flex; flex-direction: column;
  background: var(--pw-bg-surface);
}
.pw-chatpage[hidden] { display: none; }
.pw-chatpage:focus { outline: none; }
.pw-chatpage__bar {
  flex: none; position: relative;
  display: flex; align-items: center; justify-content: center;
  min-height: 56px; padding: var(--pw-space-5) calc(var(--pw-space-16) * 2);
}
.pw-chatpage__bar > .pw-btn:first-child { position: absolute; inset-inline-start: var(--pw-space-7); }
.pw-chatpage__bar > [data-pw-menu-root] { position: absolute; inset-inline-end: var(--pw-space-7); }
.pw-chatpage__title {
  margin: 0; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-chatpage__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.pw-chatpage__col { max-width: 768px; margin-inline: auto; padding: var(--pw-space-8) var(--pw-space-8) var(--pw-space-10); }
.pw-chatpage__dock { flex: none; padding: var(--pw-space-6) var(--pw-space-8) var(--pw-space-7); }
/* The answer's place, as the same card the map uses. */
.pw-chatpage .pw-amap__place { margin-block-start: var(--pw-space-6); max-width: 100%; }
/* The photograph the question came from sits on top of it, like an attachment. */
.pw-msg--user.has-photo { flex-direction: column; align-items: flex-end; gap: var(--pw-space-3); }
.pw-msg__photo { display: block; width: 160px; aspect-ratio: 4 / 3; border-radius: var(--pw-radius-lg); object-fit: cover; background: var(--pw-bg-muted); }
/* -- How busy, hour by hour ----------------------------------------------------
   An answer to "is it busy?" shows the evening as bars, one an hour, with now
   marked in the brand colour and said in words under it. The bar heights are
   the only data; `--h` is 0 to 1 on each. */
.pw-busy { margin-block-start: var(--pw-space-6); max-width: 360px; }
.pw-busy__bars {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; align-items: end; gap: var(--pw-space-2);
  height: 72px; padding-block-end: var(--pw-space-2);
  border-block-end: 1px solid var(--pw-border-subtle);
}
.pw-busy__bar { height: calc(var(--h, 0) * 100%); min-height: 3px; border-radius: var(--pw-radius-xs) var(--pw-radius-xs) 0 0; background: var(--pw-bg-muted); }
.pw-busy__bar.is-now { background: var(--pw-fg-brand); }
.pw-busy__hours { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: var(--pw-space-2); text-align: center; margin-block-start: var(--pw-space-2); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-busy__now { margin: var(--pw-space-3) 0 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); }
.pw-busy__now strong { color: var(--pw-fg-brand); }

/* -- Stop --------------------------------------------------------------------
   While an answer is being written, Send becomes Stop in the same place: the
   one control the reader needs in that moment, where their thumb already is.
   The square is the universal "stop" and needs no word beside it. */
.pw-composer [data-pw-composer-stop] { display: none; }
.pw-composer.is-answering [data-pw-composer-stop] { display: inline-flex; }
.pw-composer.is-answering [data-pw-composer-send] { display: none; }
/* Something written while it answers: Send comes back beside Stop, and now
   queues rather than sends. */
.pw-composer.is-answering.has-value [data-pw-composer-send] { display: inline-flex; }

/* -- Queued messages ------------------------------------------------------------
   At the top of the composer, in order: what will be sent next, and when. The
   first says "Sends after this answer"; each can go back into the field to be
   edited, or be removed. */
.pw-composer__queue { display: flex; flex-direction: column; gap: var(--pw-space-2); padding: var(--pw-space-5) var(--pw-space-5) 0; }
.pw-composer__queue[hidden] { display: none; }
.pw-queued {
  display: flex; align-items: center; gap: var(--pw-space-4);
  min-height: 36px; padding: var(--pw-space-1) var(--pw-space-2) var(--pw-space-1) var(--pw-space-5);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-muted);
  font-size: var(--pw-text-sm-size); color: var(--pw-fg-primary);
}
.pw-queued > .pw-icon { flex: none; color: var(--pw-fg-tertiary); }
.pw-queued__text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-queued__when { flex: none; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
/* -- Model --------------------------------------------------------------------
   Which model answers, beside Send: its name and a chevron, quiet until it is
   needed -- the choice most people make once. The menu names each model in the
   product's own words and says what it is for, never who makes it. */
.pw-composer__model { gap: var(--pw-space-1); padding-inline: var(--pw-space-4) var(--pw-space-3); color: var(--pw-fg-secondary); font-weight: var(--pw-font-weight-medium); }
.pw-composer__model .pw-icon { color: var(--pw-fg-tertiary); }
.pw-composer__model[aria-expanded="true"] .pw-icon { transform: rotate(180deg); }
.pw-model-menu { width: 300px; padding: var(--pw-space-2); }
.pw-model-menu .pw-select__option--rich { gap: var(--pw-space-5); }
.pw-model-menu .pw-select__option-title { display: flex; align-items: center; gap: var(--pw-space-3); }

@container (max-width: 560px) { .pw-queued__when { display: none; } }
.pw-stopmark { display: block; width: 10px; height: 10px; border-radius: 2px; background: currentColor; }
/* Stopped part-way: what arrived stays, dimmed a step, so it reads as
   unfinished rather than as a short answer. */
.pw-msg.is-stopped .pw-msg__body > p:not(.pw-msg__status) { color: var(--pw-fg-tertiary); }

/* -- Generated images ----------------------------------------------------------
   A set of pictures from one prompt, in a 2-up grid at the prompt's ratio.
   While one is being made its tile is a halftone field forming, with the
   size it will be and how far along it is, and when it arrives it develops
   from blur, like a print. The prompt stays under the set, so the pictures always
   say what they were asked to be. Each tile opens in the viewer; its own
   quick actions sit on its corner. */
.pw-imagegen { margin-block-start: var(--pw-space-6); max-width: 520px; }
.pw-imagegen__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--pw-space-3); }
.pw-imagegen--single .pw-imagegen__grid { grid-template-columns: minmax(0, 1fr); max-width: 360px; }
.pw-imagegen__tile {
  position: relative; margin: 0; overflow: hidden;
  aspect-ratio: var(--pw-imagegen-ratio, 1);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-muted);
}
.pw-imagegen__tile > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pw-imagegen__tile.is-pending > img { visibility: hidden; }
.pw-imagegen__tile.is-pending { background: var(--pw-bg-subtle); box-shadow: inset 0 0 0 1px var(--pw-border-faint); }
/* The canvas forming: a halftone field of neutral dots with soft masses
   drifting through it, the dots swelling and darkening where a mass passes,
   as if the picture were deciding where its weight goes. The controller draws
   it (`.pw-imagegen__field`) and hands over to the picture when it lands. */
.pw-imagegen__field { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--pw-fg-primary); pointer-events: none; }
.pw-imagegen__res, .pw-imagegen__pct {
  position: absolute; z-index: 1;
  padding: 2px var(--pw-space-3); border-radius: var(--pw-radius-sm);
  background: color-mix(in srgb, var(--pw-bg-surface) 88%, transparent);
  font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 11px; line-height: 16px; color: var(--pw-fg-tertiary);
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.pw-imagegen__res { inset-block-start: var(--pw-space-3); inset-inline-end: var(--pw-space-3); }
.pw-imagegen__pct { inset-block-end: var(--pw-space-3); inset-inline-start: var(--pw-space-3); }
.pw-imagegen__open {
  position: absolute; inset: 0; z-index: 1;
  padding: 0; border: 0; background: transparent; cursor: zoom-in;
  border-radius: inherit;
}
.pw-imagegen__open:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: -2px; }
.pw-imagegen__tile.is-pending .pw-imagegen__open, .pw-imagegen__tile.is-pending .pw-imagegen__tools { display: none; }
.pw-imagegen__tools {
  position: absolute; z-index: 2; inset-block-start: var(--pw-space-3); inset-inline-end: var(--pw-space-3);
  display: flex; gap: var(--pw-space-2);
  opacity: 0; transition: opacity var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-imagegen__tools .pw-btn { background: var(--pw-bg-lightbox); color: var(--pw-color-white); border-color: transparent; }
.pw-imagegen__tile:is(:hover, :focus-within) .pw-imagegen__tools { opacity: 1; }
@media (hover: none) { .pw-imagegen__tools { opacity: 1; } }
.pw-imagegen__prompt {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-3);
  margin: var(--pw-space-4) 0 0;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
}
.pw-imagegen__prompt q { color: var(--pw-fg-secondary); }

/* -- The viewer ---------------------------------------------------------------
   One picture at a time on the lightbox: dark in both themes, because a
   picture is judged on dark and a pale surround in dark mode lights the room.
   The prompt and the set's actions are under it, the counter and Close above,
   the arrows either side when there is more than one. */
.pw-imgview {
  position: fixed; inset: 0; z-index: var(--pw-z-modal);
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  background: var(--pw-bg-lightbox);
  backdrop-filter: blur(var(--pw-blur-lightbox));
  color: var(--pw-color-white);
}
.pw-imgview[hidden] { display: none; }
.pw-imgview__bar, .pw-imgview__foot { display: flex; align-items: center; gap: var(--pw-space-4); padding: var(--pw-space-6) var(--pw-space-8); }
.pw-imgview__count { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); }
.pw-imgview__bar > :last-child { margin-inline-start: auto; }
.pw-imgview__stage { position: relative; display: grid; place-items: center; min-height: 0; padding: 0 calc(var(--pw-space-16) * 2); }
.pw-imgview__img { max-width: 100%; max-height: 100%; border-radius: var(--pw-radius-lg); object-fit: contain; box-shadow: var(--pw-shadow-xl); }
.pw-imgview__step { position: absolute; inset-block-start: 50%; translate: 0 -50%; }
.pw-imgview__step[data-pw-imgview-step="-1"] { inset-inline-start: var(--pw-space-8); }
.pw-imgview__step[data-pw-imgview-step="1"] { inset-inline-end: var(--pw-space-8); }
[dir="rtl"] .pw-imgview__step .pw-icon { transform: scaleX(-1); }
.pw-imgview .pw-btn--ghost { color: var(--pw-color-white); }
.pw-imgview .pw-btn--ghost:hover { background: color-mix(in srgb, var(--pw-color-white) 14%, transparent); }
.pw-imgview .pw-btn--secondary { background: color-mix(in srgb, var(--pw-color-white) 12%, transparent); border-color: transparent; color: var(--pw-color-white); }
.pw-imgview .pw-btn--secondary:hover { background: color-mix(in srgb, var(--pw-color-white) 22%, transparent); }
.pw-imgview__prompt { flex: 1 1 auto; min-width: 0; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--pw-text-sm-size); opacity: .8; }
@media (max-width: 640px) {
  .pw-imgview__stage { padding: 0 var(--pw-space-6); }
  .pw-imgview__step { display: none; }
  .pw-imgview__foot { flex-wrap: wrap; }
  .pw-imgview__prompt { flex-basis: 100%; white-space: normal; }
}

/* -- Activity: what the assistant is doing --------------------------------------
   While it works, the steps are open and the head counts the seconds: each
   step a line on a thread -- a spinner while it runs, its own glyph when done,
   the danger colour when it failed. A step that would act for the reader
   (book, send, buy) stops and asks first, in the list, where the reader is
   already looking. When the work ends the list folds to the one quiet line the
   work row uses, and opens again on demand. */
.pw-activity { margin-block-end: var(--pw-space-6); }
.pw-activity__head {
  display: inline-flex; align-items: center; gap: var(--pw-space-3);
  padding: var(--pw-space-2) 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-tertiary);
}
.pw-activity__head:hover { color: var(--pw-fg-secondary); }
.pw-activity__head:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: 2px; border-radius: var(--pw-radius-xs); }
.pw-activity__head > .pw-icon { color: var(--pw-fg-quaternary); transition: transform var(--pw-duration-fast) var(--pw-ease-out); }
.pw-activity__head[aria-expanded="true"] > .pw-icon:last-child { transform: rotate(180deg); }
.pw-activity.is-live .pw-activity__title { color: var(--pw-fg-secondary); }
.pw-activity__meta { font-variant-numeric: tabular-nums; }
.pw-activity__steps { list-style: none; margin: var(--pw-space-3) 0 0; padding: 0; }
.pw-activity__step { position: relative; display: flex; gap: var(--pw-space-5); padding-block-end: var(--pw-space-5); }
/* The thread between steps. */
.pw-activity__step:not(:last-child)::before {
  content: ""; position: absolute; inset-inline-start: 9px; inset-block: 22px 2px;
  width: 1px; background: var(--pw-border-subtle);
}
.pw-activity__icon {
  flex: none; display: grid; place-items: center; width: 20px; height: 20px;
  border-radius: var(--pw-radius-circle); background: var(--pw-bg-muted); color: var(--pw-fg-tertiary);
}
.pw-activity__icon .pw-spinner { width: 12px; height: 12px; }
.pw-activity__step.is-active .pw-activity__icon { background: var(--pw-tint-ai-bg); color: var(--pw-tint-ai-fg); }
.pw-activity__step.is-failed .pw-activity__icon { background: var(--pw-tint-danger-bg); color: var(--pw-fg-danger); }
.pw-activity__step.is-asking .pw-activity__icon { background: var(--pw-tint-warning-bg); color: var(--pw-tint-warning-fg); }
.pw-activity__body { flex: 1 1 auto; min-width: 0; padding-block-start: 1px; }
.pw-activity__label { display: block; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-activity__step.is-active .pw-activity__label { color: var(--pw-fg-primary); }
.pw-activity__label strong { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-activity__detail { margin-block-start: var(--pw-space-2); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-activity__step.is-failed .pw-activity__detail { color: var(--pw-fg-danger); }
/* Sites read, as a row of small chips with their icons. */
.pw-activity__sites { display: flex; flex-wrap: wrap; gap: var(--pw-space-2); margin-block-start: var(--pw-space-3); }
.pw-activity__site {
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  padding: 2px var(--pw-space-4) 2px 3px; border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-muted); color: var(--pw-fg-secondary);
  font-size: var(--pw-text-xs-size); text-decoration: none;
}
.pw-activity__site:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-activity__site .pw-favicon { width: 16px; height: 16px; border: 0; }
/* Asking before acting. */
.pw-activity__ask {
  margin-block-start: var(--pw-space-4); padding: var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-activity__asktext { margin: 0 0 var(--pw-space-5); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-activity__askbar { display: flex; gap: var(--pw-space-3); }
.pw-activity__asked { margin: 0; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-activity__step.is-answered .pw-activity__ask { padding: 0; border: 0; box-shadow: none; background: none; margin-block-start: var(--pw-space-2); }
.pw-activity__step.is-declined .pw-activity__label { color: var(--pw-fg-tertiary); text-decoration: line-through; }

/* -- Usage ----------------------------------------------------------------------
   An answer made with the lighter model says so under itself, in one quiet
   line with when the full one comes back: a plan limit that changes the
   quality of answers without saying so is the thing people resent most. And
   the plan's page shows every allowance as a meter with its own reset time. */
/* A value that flips in place (PW.flipText): each character its own cell,
   the leaving and arriving digit stacked in it and clipped to the line. */
.pw-flip { display: inline-flex; white-space: pre; font-variant-numeric: tabular-nums; }
.pw-flip__ch { display: inline-grid; overflow: hidden; }
.pw-flip__ch > span { grid-area: 1 / 1; }
/* Inline text, not a flex row: the countdown inside it is a run of words, and
   flex would put a gap between every run. */
.pw-msg__model {
  display: block;
  margin-block-start: var(--pw-space-5);
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
}
.pw-msg__model .pw-icon { margin-inline-end: var(--pw-space-2); vertical-align: -2px; color: var(--pw-fg-quaternary); }
.pw-msg__model a { color: var(--pw-fg-link); text-decoration: none; }
.pw-msg__model a:hover { text-decoration: underline; }

.pw-usage { display: flex; flex-direction: column; gap: var(--pw-space-8); padding: var(--pw-space-10); border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-surface); }
.pw-usage__head { display: flex; align-items: center; gap: var(--pw-space-5); }
.pw-usage__plan { margin: 0; font-size: var(--pw-text-md-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-usage__head .pw-btn { margin-inline-start: auto; }
.pw-usage__row { display: grid; grid-template-columns: 1fr auto; gap: var(--pw-space-3) var(--pw-space-6); align-items: baseline; }
.pw-usage__name { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); }
.pw-usage__count { font-size: var(--pw-text-sm-size); font-variant-numeric: tabular-nums; color: var(--pw-fg-secondary); }
.pw-usage__row .pw-progress { grid-column: 1 / -1; }
.pw-usage__reset { grid-column: 1 / -1; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-usage__row.is-out .pw-progress__bar { background: var(--pw-fg-danger); }
.pw-usage__row.is-low .pw-progress__bar { background: var(--pw-tint-warning-fg); }

/* -- Effort: how hard to work, on a thick slider ---------------------------------
   One control, and the track is the picture. Pixels run from sparse round dots
   at the Fast end to a tight grid of square pixels at the Deep end; up to the
   handle they are lit in the brand-to-AI gradient and shimmer, past it they
   are quiet grey. The handle is a tall, semi-rounded bar -- a thing to take
   hold of, not a dot to aim at. Under it, the level's name, what it costs in
   time, and one sentence. A level the plan lacks can be looked at, is marked,
   and is not applied. */
.pw-effort { display: flex; flex-direction: column; gap: var(--pw-space-5); }
.pw-effort-menu { width: 340px; padding: var(--pw-space-7); }
.pw-effort__head { display: flex; align-items: baseline; gap: var(--pw-space-4); }
.pw-effort__name { font-size: var(--pw-text-md-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-effort__time { margin-inline-start: auto; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-effort__head .pw-tag { display: none; }
.pw-effort.is-locked .pw-effort__head .pw-tag { display: inline-flex; }
.pw-effort__track {
  position: relative; height: 72px;
  border-radius: var(--pw-radius-xl);
  background: var(--pw-skeleton-base);
  box-shadow: inset 0 0 0 1px var(--pw-border-faint);
  overflow: hidden;
  touch-action: none;
}
.pw-effort__field { position: absolute; inset: 0; width: 100%; height: 100%; }
.pw-effort__handle {
  position: absolute; inset-block: 6px; left: var(--pw-effort-x, 13px);
  width: 14px; translate: -50% 0;
  border-radius: var(--pw-radius-md);
  background: var(--pw-bg-surface);
  box-shadow: 0 0 0 1px var(--pw-border-subtle), var(--pw-shadow-md);
  pointer-events: none;
  transition: scale var(--pw-duration-fast) var(--pw-ease-out), box-shadow var(--pw-duration-fast) var(--pw-ease-out);
}
/* Two grip lines, so it reads as something to hold. */
.pw-effort__handle::before {
  content: ""; position: absolute; inset-block: 50%; inset-inline: 5px; height: 16px; translate: 0 -50%;
  border-inline: 1px solid var(--pw-border-strong);
}
.pw-effort.is-dragging .pw-effort__handle { scale: 1.08 1; box-shadow: 0 0 0 1px var(--pw-border-brand), var(--pw-shadow-lg); }
.pw-effort__input {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: grab; -webkit-appearance: none; appearance: none;
}
.pw-effort__input:active { cursor: grabbing; }
.pw-effort__track:has(.pw-effort__input:focus-visible) { box-shadow: inset 0 0 0 1px var(--pw-border-faint), var(--pw-focus-ring); }
.pw-effort.is-auto .pw-effort__track, .pw-effort.is-auto .pw-effort__stops { opacity: .45; }
.pw-effort.is-auto .pw-effort__input { cursor: not-allowed; }
/* Each label sits under its own stop: the handle's centre travels 13px in
   from each end of the track, so the stops do too. */
.pw-effort__stops { position: relative; height: 24px; margin-block-start: calc(var(--pw-space-2) * -1); }
.pw-effort__stops button {
  position: absolute; inset-block-start: 0;
  inset-inline-start: calc(var(--i, 0) / (var(--pw-effort-n, 4) - 1) * (100% - 26px) + 13px);
  translate: -50% 0;
  padding: var(--pw-space-2) 0; border: 0; background: none; cursor: pointer; white-space: nowrap;
  font: inherit; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary);
}
.pw-effort__stops button:first-child { inset-inline-start: 0; translate: none; }
.pw-effort__stops button:last-child { inset-inline-start: auto; inset-inline-end: 0; translate: none; }
[dir="rtl"] .pw-effort__stops button { translate: 50% 0; }
.pw-effort__stops button:hover { color: var(--pw-fg-primary); }
.pw-effort__stops button[aria-pressed="true"] { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-effort__stops button:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: 2px; border-radius: var(--pw-radius-xs); }
.pw-effort__desc { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-effort__upgrade { display: none; }
.pw-effort.is-locked .pw-effort__upgrade { display: flex; }
.pw-effort__auto {
  display: flex; align-items: center; gap: var(--pw-space-4);
  padding-block-start: var(--pw-space-5); border-block-start: 1px solid var(--pw-border-faint);
  font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); cursor: pointer;
}
.pw-effort__auto small { display: block; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }

/* -- History: find, pin, rename, archive ------------------------------------------
   The sidebar's chats, grouped by when -- Pinned first, then Today, Yesterday,
   the last week -- with Search at the top and one menu for every row. Search
   is a dialog over everything, not a filter on the visible rows: it reads the
   words inside chats as well as their names, and marks what matched. */
/* The specimen's sidebar: the shell's aside, on its own. */
.pw-history-frame { width: 300px; height: 560px; display: flex; flex-direction: column; padding: var(--pw-space-8) var(--pw-space-6); border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-subtle); }
.pw-history-frame > .pw-history { flex: 1 1 auto; }
.pw-history .pw-sidenav__scroll { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.pw-history { display: flex; flex-direction: column; gap: var(--pw-space-2); min-height: 0; }
.pw-history__search { color: var(--pw-fg-secondary); }
.pw-history__search .pw-sidenav__end .pw-kbd { font-family: inherit; }
.pw-history__group { display: flex; flex-direction: column; gap: var(--pw-space-1); }
.pw-history__group[hidden] { display: none; }
.pw-history__group + .pw-history__group { margin-block-start: var(--pw-space-5); }
.pw-history .pw-sidenav__item { position: relative; }
/* The row opens the chat through one button stretched across it; the menu
   button sits above that, so the two never nest. */
.pw-history__open {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center;
  padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; cursor: pointer;
}
.pw-history__open::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.pw-history__open:focus-visible { outline: none; }
.pw-history__open:focus-visible::after { outline: 2px solid var(--pw-border-brand); outline-offset: -2px; }
.pw-history__open > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-history__more { position: relative; z-index: 1; }
/* No mark on a pinned row: the Pinned heading already says which chats are
   pinned. The menu button waits for the row, keeping its space so nothing
   shifts. */
.pw-history__more {
  margin-inline-start: auto; flex: none; opacity: 0;
  transition: opacity var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-history .pw-sidenav__item:is(:hover, :focus-within, .is-current) .pw-history__more { opacity: 1; }
@media (hover: none) { .pw-history__more { opacity: 1; } }
.pw-history__rename {
  flex: 1 1 auto; min-width: 0; height: 28px; margin-inline: calc(var(--pw-space-3) * -1);
  padding: 0 var(--pw-space-3);
  border: 1px solid var(--pw-border-brand); border-radius: var(--pw-radius-md);
  background: var(--pw-bg-surface); color: var(--pw-fg-primary);
  font: inherit; outline: none; box-shadow: var(--pw-focus-ring);
}
.pw-history__menu { z-index: var(--pw-z-popover); min-width: 180px; }
.pw-history__count { font-variant-numeric: tabular-nums; }
.pw-history__empty { padding: var(--pw-space-10) var(--pw-space-5); text-align: center; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); }
.pw-history__empty .pw-icon { display: block; margin: 0 auto var(--pw-space-4); color: var(--pw-fg-quaternary); }
.pw-history__archlist { display: flex; flex-direction: column; }
.pw-history__arch { display: flex; align-items: center; gap: var(--pw-space-4); padding: var(--pw-space-4) 0; border-block-end: 1px solid var(--pw-border-faint); }
.pw-history__arch > span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--pw-text-sm-size); color: var(--pw-fg-primary); }
.pw-history__none { margin: 0; padding: var(--pw-space-8) 0; text-align: center; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); }

/* The search dialog: a field, then the matches. */
.pw-chatsearch .pw-modal__panel { padding: 0; overflow: hidden; }
.pw-chatsearch__field { display: flex; align-items: center; gap: var(--pw-space-5); padding: var(--pw-space-6) var(--pw-space-8); border-block-end: 1px solid var(--pw-border-subtle); }
.pw-chatsearch__field > .pw-icon { flex: none; color: var(--pw-fg-tertiary); }
.pw-chatsearch__input { flex: 1 1 auto; min-width: 0; border: 0; background: none; outline: none; font: inherit; font-size: var(--pw-text-md-size); color: var(--pw-fg-primary); }
.pw-chatsearch__results { max-height: min(420px, 60vh); overflow-y: auto; padding: var(--pw-space-3); }
.pw-chatsearch__label { margin: var(--pw-space-3) var(--pw-space-5) var(--pw-space-2); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary); }
.pw-chatsearch__hit {
  display: flex; align-items: flex-start; gap: var(--pw-space-5); width: 100%;
  padding: var(--pw-space-5); border: 0; border-radius: var(--pw-radius-lg);
  background: none; text-align: start; font: inherit; color: inherit; cursor: pointer;
}
.pw-chatsearch__hit > .pw-icon { flex: none; margin-block-start: 2px; color: var(--pw-fg-quaternary); }
.pw-chatsearch__hit.is-active, .pw-chatsearch__hit:hover { background: var(--pw-bg-hover); }
.pw-chatsearch__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--pw-space-1); }
.pw-chatsearch__title { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-chatsearch__snippet { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-chatsearch__when { flex: none; font-size: var(--pw-text-xs-size); color: var(--pw-fg-quaternary); }
.pw-chatsearch mark { background: var(--pw-tint-warning-bg); color: var(--pw-fg-primary); border-radius: 2px; padding: 0 1px; }
.pw-chatsearch__none { margin: 0; padding: var(--pw-space-10); text-align: center; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); }
.pw-chatsearch__foot { display: flex; gap: var(--pw-space-6); padding: var(--pw-space-4) var(--pw-space-8); border-block-start: 1px solid var(--pw-border-subtle); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }

/* -- Start: a new chat --------------------------------------------------------------
   The orb, looking about, over a greeting by the reader's clock; the composer;
   and under it the starters. A starter opens a few example prompts in place --
   the answer to "like what?" -- and a prompt goes into the composer to be
   edited, never sent on the reader's behalf. When there is a recent chat worth
   going back to, one card offers it. */
.pw-start { display: flex; flex-direction: column; align-items: center; gap: var(--pw-space-8); width: 100%; max-width: 720px; margin-inline: auto; padding: var(--pw-space-16) var(--pw-space-8); }
.pw-start__orb { --pw-orb-size: 56px; }
.pw-start__greet { margin: 0; text-align: center; font-size: var(--pw-text-display-xs-size, var(--pw-text-xl-size)); line-height: 1.25; font-weight: var(--pw-font-weight-bold); color: var(--pw-fg-primary); }
.pw-start__sub { margin: calc(var(--pw-space-6) * -1) 0 0; text-align: center; font-size: var(--pw-text-md-size); color: var(--pw-fg-tertiary); }
.pw-start > .pw-composer-dock { width: 100%; }
.pw-start__starters { justify-content: safe center; width: 100%; }
.pw-start__prompts { display: flex; flex-direction: column; width: 100%; margin-block-start: calc(var(--pw-space-5) * -1); border-radius: var(--pw-radius-xl); }
.pw-start__prompts[hidden] { display: none; }
.pw-start__prompt {
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-5) var(--pw-space-6); border: 0; border-block-end: 1px solid var(--pw-border-faint);
  background: none; color: var(--pw-fg-secondary); font: inherit; font-size: var(--pw-text-sm-size); text-align: start; cursor: pointer;
}
.pw-start__prompt:last-child { border-block-end: 0; }
.pw-start__prompt:hover { color: var(--pw-fg-primary); background: var(--pw-bg-hover); border-radius: var(--pw-radius-lg); }
.pw-start__prompt > .pw-icon { flex: none; color: var(--pw-fg-quaternary); }
/* The last chat, set apart from the starters: further down, under its own
   small grey title, so it reads as "where you were" rather than one more way
   to begin. */
.pw-start__recent { display: flex; flex-direction: column; gap: var(--pw-space-4); width: 100%; margin-block-start: var(--pw-space-12); }
.pw-start__recent-label { margin: 0; padding-inline: var(--pw-space-2); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-tertiary); }
.pw-start__resume {
  display: flex; align-items: center; gap: var(--pw-space-6); width: 100%;
  padding: var(--pw-space-6) var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface); color: inherit; font: inherit; text-align: start; cursor: pointer;
}
.pw-start__resume:hover { border-color: var(--pw-border-default); box-shadow: var(--pw-shadow-xs); }
.pw-start__resume-icon { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: var(--pw-radius-lg); background: var(--pw-tint-ai-bg); color: var(--pw-tint-ai-fg); }
.pw-start__resume-body { flex: 1 1 auto; min-width: 0; }
.pw-start__resume-kicker { display: block; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-start__resume-title { display: block; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-start__resume > .pw-icon:last-child { flex: none; color: var(--pw-fg-quaternary); }

/* -- Tour: the coach mark, walked through steps ---------------------------------- */
.pw-tour { position: fixed; z-index: var(--pw-z-popover); }
/* No cover: a tour points at the real thing, so the thing is the picture. */
.pw-tour { padding: var(--pw-space-5); text-align: start; }
.pw-tour .pw-coach__title { justify-content: flex-start; margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); }
.pw-tour .pw-coach__text { margin: var(--pw-space-2) 0 0; }
.pw-tour .pw-coach__actions { margin: var(--pw-space-5) 0 0; }
.pw-tour__count { margin-inline-end: auto; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-tour-ring {
  position: fixed; z-index: var(--pw-z-popover); pointer-events: none;
  border-radius: var(--pw-radius-xl);
  box-shadow: 0 0 0 2px var(--pw-color-brand-500), 0 0 0 6px color-mix(in srgb, var(--pw-color-brand-500) 22%, transparent);
}

/* -- What this answer used ---------------------------------------------------------
   Invisible context is what people distrust most about an assistant, so every
   answer can say what it drew on: the web, memory, location, a file. Each is a
   row with a switch; turning some off and answering again is the way to find
   out whether it mattered. The panel opens under the answer, in the flow --
   it is about this answer, not a setting. */
.pw-msg__actions .pw-used-btn { gap: var(--pw-space-3); padding-inline: var(--pw-space-4); color: var(--pw-fg-tertiary); }
.pw-msg__actions .pw-used-btn:hover, .pw-msg__actions .pw-used-btn.is-selected { color: var(--pw-fg-primary); }
.pw-msg__actions .pw-used-btn { margin-inline-start: auto; }
.pw-used {
  margin-block-start: var(--pw-space-4);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
}
.pw-used__head { display: flex; align-items: center; gap: var(--pw-space-4); padding: var(--pw-space-6) var(--pw-space-7) var(--pw-space-3); font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-used__head .pw-icon { color: var(--pw-fg-brand); }
.pw-used__row { display: flex; align-items: center; gap: var(--pw-space-5); padding: var(--pw-space-4) var(--pw-space-7); }
.pw-used__icon { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--pw-radius-md); background: var(--pw-bg-muted); color: var(--pw-fg-secondary); }
.pw-used__body { flex: 1 1 auto; min-width: 0; }
.pw-used__name { display: block; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); }
.pw-used__detail { display: block; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-used__row.is-off .pw-used__name, .pw-used__row.is-off .pw-used__icon { color: var(--pw-fg-quaternary); }
.pw-used__row.is-off .pw-used__name { text-decoration: line-through; }
.pw-used__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-4); padding: var(--pw-space-5) var(--pw-space-7) var(--pw-space-6); border-block-start: 1px solid var(--pw-border-faint); margin-block-start: var(--pw-space-3); }
.pw-used__again-note { flex: 1 1 200px; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-used__promise { display: flex; align-items: center; gap: var(--pw-space-3); width: 100%; margin: 0; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-used__promise .pw-icon { color: var(--pw-fg-success); }

/* -- Answers it can't give, and answers with a caveat ------------------------------
   Four notes, one shape: an icon, a line in bold that says the situation, a
   sentence of why, and a way on. Declining is NEUTRAL -- it is an answer, and
   dressing it as an error says the product broke. A caution sits above the
   answer it qualifies, in the warning tint, short enough to read. Urgent is
   the only one in the danger tint, and it leads with the number to call.
   "Sources disagree" is information, and says which way each side goes. */
.pw-caveat {
  display: flex; gap: var(--pw-space-5);
  margin-block: 0 var(--pw-space-6);
  padding: var(--pw-space-6) var(--pw-space-7);
  border-radius: var(--pw-radius-xl);
  background: var(--pw-skeleton-base);
  border: 1px solid var(--pw-border-faint);
}
.pw-caveat > .pw-icon { flex: none; margin-block-start: 2px; color: var(--pw-fg-tertiary); }
.pw-caveat__body { flex: 1 1 auto; min-width: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-caveat__title { display: block; margin-block-end: var(--pw-space-1); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-caveat__body p { margin: 0; }
.pw-caveat__actions { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); margin-block-start: var(--pw-space-5); }
.pw-caveat--caution { background: var(--pw-tint-warning-bg); border-color: transparent; }
.pw-caveat--caution > .pw-icon { color: var(--pw-tint-warning-fg); }
.pw-caveat--urgent { background: var(--pw-tint-danger-bg); border-color: transparent; }
.pw-caveat--urgent > .pw-icon, .pw-caveat--urgent .pw-caveat__title { color: var(--pw-tint-danger-fg); }
.pw-caveat--unsure { background: var(--pw-tint-brand-bg); border-color: transparent; }
.pw-caveat--unsure > .pw-icon { color: var(--pw-tint-brand-fg); }
.pw-caveat__call { font-variant-numeric: tabular-nums; }
/* Two sides, side by side. */
.pw-caveat__sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--pw-space-4); margin-block-start: var(--pw-space-5); }
.pw-caveat__side { padding: var(--pw-space-5); border-radius: var(--pw-radius-lg); background: var(--pw-bg-surface); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); }
.pw-caveat__side b { display: block; margin-block-end: var(--pw-space-1); font-size: var(--pw-text-sm-size); color: var(--pw-fg-primary); }
@media (max-width: 560px) { .pw-caveat__sides { grid-template-columns: 1fr; } }

/* -- Not sent, not finished ---------------------------------------------------------
   The reader's own message says what happened to it, under the bubble: waiting
   for a connection (quiet, with a clock) or not sent (danger, with Retry). The
   words are never lost -- a failed message stays in the thread, editable. An
   answer that broke part-way keeps what arrived and says where it stopped. */
.pw-msg--user.has-delivery { flex-direction: column; align-items: flex-end; gap: var(--pw-space-2); }
.pw-msg--user.is-pending > .pw-msg__body { opacity: .6; }
.pw-msg--user.is-failed > .pw-msg__body { box-shadow: inset 0 0 0 1px var(--pw-border-danger); }
.pw-msg__delivery { display: flex; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-msg--user.is-failed .pw-msg__delivery { color: var(--pw-fg-danger); }
.pw-msg__delivery .pw-btn { margin-inline-start: var(--pw-space-1); }
/* Offline: the composer says so at its top, and keeps taking messages. */
.pw-composer__notice--offline { background: var(--pw-tint-warning-bg); color: var(--pw-tint-warning-fg); }
/* Where an answer broke: a hairline across the text at that point. */
.pw-msg__break { display: flex; align-items: center; gap: var(--pw-space-4); margin-block: var(--pw-space-4); font-size: var(--pw-text-xs-size); color: var(--pw-fg-danger); }
.pw-msg__break::before, .pw-msg__break::after { content: ""; flex: 1 1 auto; height: 1px; background: var(--pw-border-danger); opacity: .4; }

/* -- Shopping, answered -------------------------------------------------------------
   Picks, not a result grid: three at most, each with the one reason it is
   here ("Best overall", "Lightest") and a line of why. A pick opens where to
   buy it; Compare asks for them side by side, and the comparison comes back
   as its own answer. The answer says when prices were checked and
   that PrivacyWall earns nothing from the links -- the two things that decide
   whether a buying answer can be trusted. */
.pw-shopans { display: flex; flex-direction: column; gap: var(--pw-space-6); margin-block-start: var(--pw-space-5); }
.pw-shopans__picks { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--pw-space-4); }
.pw-pick {
  position: relative; display: flex; flex-direction: column;
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface); overflow: hidden;
  transition: border-color var(--pw-duration-fast) var(--pw-ease-out), box-shadow var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-pick:hover { border-color: var(--pw-border-default); }
.pw-pick.is-chosen { border-color: var(--pw-fg-primary); }
.pw-pick__main { display: flex; flex-direction: column; gap: var(--pw-space-2); padding: 0 0 var(--pw-space-5); border: 0; background: none; font: inherit; color: inherit; text-align: start; cursor: pointer; }
.pw-pick__main:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: -2px; border-radius: var(--pw-radius-xl); }
.pw-pick__media { display: block; aspect-ratio: 4 / 3; margin-block-end: var(--pw-space-4); background: var(--pw-bg-muted); }
.pw-pick__badge {
  position: absolute; inset-block-start: var(--pw-space-4); inset-inline-start: var(--pw-space-4);
  padding: 2px var(--pw-space-4); border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-surface); box-shadow: var(--pw-shadow-xs);
  font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
  pointer-events: none;
}
.pw-pick__title, .pw-pick__why, .pw-pick .pw-price, .pw-pick__from { padding-inline: var(--pw-space-5); }
.pw-pick__title { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-pick__why { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); }
.pw-pick__from { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-shopans__offers { border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); padding: 0 var(--pw-space-7); }
.pw-shopans__offers[hidden] { display: none; }
.pw-shopans__offers .pw-offer:last-child { border-bottom: 0; }
.pw-shopans__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-4); }
.pw-shopans__watch-note { font-size: var(--pw-text-xs-size); color: var(--pw-fg-secondary); }
.pw-shopans [data-pw-watch][aria-pressed="true"] { color: var(--pw-fg-brand); border-color: var(--pw-border-brand); }
.pw-shopans__trust { display: flex; align-items: center; gap: var(--pw-space-3); margin: 0; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }

/* -- Scheduled tasks ----------------------------------------------------------------
   Something the assistant will do later is a card the reader can see and stop:
   what it watches, how often, when it next looks, and what it last found. The
   state is on the card in words and in the dot -- running, paused, done,
   stopped -- and a result arrives in the thread tagged with the task it came
   from, so a message nobody just asked for is never a mystery. */
.pw-sched {
  display: flex; flex-direction: column; gap: var(--pw-space-5);
  margin-block-start: var(--pw-space-5); padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
}
.pw-sched__head { display: flex; align-items: flex-start; gap: var(--pw-space-5); }
.pw-sched__icon { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: var(--pw-radius-lg); background: var(--pw-tint-ai-bg); color: var(--pw-tint-ai-fg); }
.pw-sched__title { display: block; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-sched__when { display: flex; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-sched__dot { width: 8px; height: 8px; border-radius: var(--pw-radius-circle); background: var(--pw-fg-success); }
.pw-sched[data-state="paused"] .pw-sched__dot { background: var(--pw-tint-warning-fg); }
.pw-sched[data-state="stopped"] .pw-sched__dot, .pw-sched[data-state="done"] .pw-sched__dot { background: var(--pw-fg-quaternary); }
.pw-sched__status { margin: 0; padding: var(--pw-space-4) var(--pw-space-5); border-radius: var(--pw-radius-lg); background: var(--pw-bg-subtle); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); }
.pw-sched[data-state="stopped"] { background: var(--pw-bg-subtle); }
.pw-sched[data-state="stopped"] .pw-sched__title { color: var(--pw-fg-tertiary); }
.pw-sched__actions { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); }
/* A result, in the thread: tagged with its task. */
/* A result's fare, opened in place under it. */
.pw-tk-flight { display: flex; flex-direction: column; gap: var(--pw-space-3); margin-block-start: var(--pw-space-5); }
.pw-tk-flight[hidden] { display: none; }
.pw-tk-legs { border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); overflow: hidden; }
.pw-tk-leg { display: flex; align-items: center; gap: var(--pw-space-6); padding: var(--pw-space-6) var(--pw-space-7); }
.pw-tk-leg + .pw-tk-leg { border-block-start: 1px solid var(--pw-border-faint); }
.pw-tk-leg__date { flex: none; width: 48px; display: flex; flex-direction: column; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-tk-leg__date b { font-size: var(--pw-text-sm-size); color: var(--pw-fg-primary); }
.pw-tk-leg__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--pw-space-1); }
.pw-tk-leg__times { font-size: var(--pw-text-md-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); font-variant-numeric: tabular-nums; }
.pw-tk-leg__times sup { font-size: 10px; color: var(--pw-fg-tertiary); }
.pw-tk-leg__route { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); }
.pw-tk-leg__price { flex: none; display: flex; flex-direction: column; align-items: flex-end; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-tk-legs__airline { display: flex; align-items: center; gap: var(--pw-space-3); margin: 0; padding: var(--pw-space-4) var(--pw-space-7); border-block-start: 1px solid var(--pw-border-faint); background: var(--pw-bg-subtle); font-size: var(--pw-text-xs-size); color: var(--pw-fg-secondary); }
.pw-tk-flight__book { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-5); margin-block-start: var(--pw-space-3); }
.pw-tk-flight__note { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-msg__from { display: inline-flex; align-items: center; gap: var(--pw-space-3); margin-block-end: var(--pw-space-4); padding: 2px var(--pw-space-4); border-radius: var(--pw-radius-pill); background: var(--pw-tint-ai-bg); color: var(--pw-tint-ai-fg); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-medium); }
/* The list of every task. */
.pw-scheds { border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-surface); }
.pw-scheds .pw-sched { flex-direction: row; align-items: center; margin: 0; padding: var(--pw-space-6) var(--pw-space-7); border: 0; border-radius: 0; background: none; }
.pw-scheds .pw-sched + .pw-sched { border-block-start: 1px solid var(--pw-border-faint); }
.pw-scheds .pw-sched__head { flex: 1 1 auto; min-width: 0; align-items: center; }
.pw-scheds .pw-sched__status { display: none; }
.pw-sched__switch { flex: none; }
/* Editing a task: its terms as fields, in the card. */
.pw-sched__edit { display: flex; flex-direction: column; gap: var(--pw-space-5); padding: var(--pw-space-6); border-radius: var(--pw-radius-lg); background: var(--pw-bg-subtle); }
.pw-sched__edit[hidden] { display: none; }
.pw-sched__field { display: flex; flex-direction: column; gap: var(--pw-space-2); }
.pw-sched__field > span { font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-secondary); }
.pw-sched__row { display: flex; flex-wrap: wrap; gap: var(--pw-space-5); }
.pw-sched__row > .pw-sched__field { flex: 1 1 140px; }
.pw-sched__edit-bar { display: flex; gap: var(--pw-space-3); }
.pw-sched.is-editing .pw-sched__actions, .pw-sched.is-editing .pw-sched__status { display: none; }

/* -- Other languages, and right to left -------------------------------------------
   Each message takes its own direction from its own text (`dir="auto"`), so an
   Arabic answer in an English thread reads right to left inside its column
   while the thread keeps its shape. Arabic is set in the platform's Arabic
   face, a touch larger and with more leading, because Arabic at Latin sizes
   reads small. A translation swaps in place and says what it is. */
.pw-msg__body:lang(ar), .pw-msg__body [lang="ar"], [dir="rtl"] .pw-msg__body {
  font-family: var(--pw-font-arabic);
}
.pw-msg__body:lang(ar), .pw-msg__body [lang="ar"] { font-size: calc(var(--pw-text-sm-size) + 1px); line-height: 1.9; }
.pw-tr__note { display: flex; align-items: center; gap: var(--pw-space-3); margin: var(--pw-space-4) 0 0; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-tr__note[hidden] { display: none; }
.pw-tr.is-loading {
  min-height: 3lh; border-radius: var(--pw-radius-md);
  background: linear-gradient(90deg, var(--pw-bg-muted) 25%, var(--pw-bg-subtle) 50%, var(--pw-bg-muted) 75%) 0 0 / 200% 100%;
  animation: pw-tr-shimmer 1.4s linear infinite;
}
@keyframes pw-tr-shimmer { to { background-position: -200% 0; } }
.pw-msg__lang { display: inline-flex; align-items: center; gap: var(--pw-space-2); margin-inline-start: var(--pw-space-3); font-size: var(--pw-text-xs-size); color: var(--pw-fg-quaternary); }

/* -- Media from the web: videos, posts, articles ------------------------------------
   The assistant can point at a video, a post or an article when that is the
   best answer. Each keeps its source's identity -- the platform's own mark,
   the account, the site -- and says why it is here. Nothing from another site
   loads until the reader asks: a video is a still with a play button, and the
   first play says where it plays from and asks. Posts are drawn from their
   text, not embedded, so reading them costs no tracking at all. */
.pw-media { display: flex; flex-direction: column; gap: var(--pw-space-5); margin-block-start: var(--pw-space-5); }

/* Video */
.pw-vid { max-width: 520px; border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-surface); overflow: hidden; }
.pw-vid__stage { position: relative; aspect-ratio: 16 / 9; background: var(--pw-color-gray-950); overflow: hidden; }
.pw-vid__stage > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: opacity var(--pw-duration-base) var(--pw-ease-out), filter var(--pw-duration-base) var(--pw-ease-out); }
.pw-vid__play {
  position: absolute; inset: 0; display: grid; place-items: center;
  border: 0; background: linear-gradient(to top, var(--pw-bg-lightbox), transparent 55%); cursor: pointer;
}
.pw-vid__play-disc {
  display: grid; place-items: center; width: 64px; height: 64px; border-radius: var(--pw-radius-circle);
  background: color-mix(in srgb, var(--pw-color-white) 92%, transparent); color: var(--pw-color-gray-950);
  box-shadow: var(--pw-shadow-lg); transition: scale var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-vid__play:hover .pw-vid__play-disc { scale: 1.06; }
.pw-vid__play:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: -4px; }
.pw-vid__badge { position: absolute; inset-block-end: var(--pw-space-4); inset-inline-end: var(--pw-space-4); padding: 1px var(--pw-space-3); border-radius: var(--pw-radius-xs); background: var(--pw-bg-lightbox); color: var(--pw-color-white); font-size: var(--pw-text-xs-size); font-variant-numeric: tabular-nums; pointer-events: none; }
.pw-vid__brand { position: absolute; inset-block-start: var(--pw-space-4); inset-inline-start: var(--pw-space-4); display: flex; align-items: center; gap: var(--pw-space-2); padding: 3px var(--pw-space-4) 3px var(--pw-space-3); border-radius: var(--pw-radius-pill); background: var(--pw-bg-lightbox); color: var(--pw-color-white); font-size: var(--pw-text-xs-size); pointer-events: none; }
/* Asking before anything loads. */
.pw-vid__consent {
  position: absolute; inset: 0; display: none; flex-direction: column; justify-content: center; gap: var(--pw-space-5);
  padding: var(--pw-space-8) var(--pw-space-10);
  background: var(--pw-bg-lightbox); backdrop-filter: blur(var(--pw-blur-lightbox)); color: var(--pw-color-white);
}
.pw-vid[data-state="asking"] .pw-vid__consent { display: flex; }
.pw-vid[data-state="asking"] .pw-vid__play { display: none; }
.pw-vid__consent p { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); }
.pw-vid__consent p b { display: block; margin-block-end: var(--pw-space-1); font-size: var(--pw-text-md-size); }
.pw-vid__consent-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-4); }
.pw-vid__consent label { display: flex; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); opacity: .9; cursor: pointer; }
.pw-vid__consent .pw-btn--ghost { color: var(--pw-color-white); }
/* Playing: the product's player, or here a stand-in that says what it would do. */
.pw-vid__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.pw-vid__playing { position: absolute; inset: 0; display: none; flex-direction: column; justify-content: flex-end; gap: var(--pw-space-3); padding: var(--pw-space-6); color: var(--pw-color-white); background: linear-gradient(to top, var(--pw-bg-lightbox), transparent 60%); }
.pw-vid[data-state="playing"] .pw-vid__playing { display: flex; }
.pw-vid[data-state="playing"] .pw-vid__play, .pw-vid[data-state="playing"] .pw-vid__badge { display: none; }
.pw-vid[data-state="playing"]:has(.pw-vid__frame) .pw-vid__playing { display: none; }
.pw-vid__bar { height: 3px; border-radius: var(--pw-radius-pill); background: color-mix(in srgb, var(--pw-color-white) 30%, transparent); overflow: hidden; }
.pw-vid__bar::after { content: ""; display: block; height: 100%; width: 35%; background: var(--pw-color-danger-500); animation: pw-vid-run 12s linear infinite; }
@keyframes pw-vid-run { from { width: 5%; } to { width: 100%; } }
.pw-vid__playing span { font-size: var(--pw-text-xs-size); }
.pw-vid__info { display: flex; flex-direction: column; gap: var(--pw-space-2); padding: var(--pw-space-6) var(--pw-space-7) var(--pw-space-5); }
.pw-vid__title { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-vid__meta { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-vid__moments { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); padding: 0 var(--pw-space-7) var(--pw-space-6); }
.pw-vid__moments .pw-chip { font-variant-numeric: tabular-nums; }
.pw-vid__moments .pw-chip b { color: var(--pw-fg-link); font-weight: var(--pw-font-weight-semibold); }

/* Posts: X, Instagram, Facebook -- one shape, the platform's mark on it. */
.pw-post { display: flex; flex-direction: column; gap: var(--pw-space-4); max-width: 520px; padding: var(--pw-space-7); border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-surface); }
.pw-post__head { display: flex; align-items: center; gap: var(--pw-space-4); }
.pw-post__avatar { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: var(--pw-radius-circle); background: var(--pw-bg-muted); color: var(--pw-fg-secondary); font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); overflow: hidden; }
.pw-post__avatar img { width: 100%; height: 100%; object-fit: cover; }
.pw-post__who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.pw-post__name { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-post__handle { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-post__platform { flex: none; color: var(--pw-fg-primary); }
.pw-post__text { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-md-line); color: var(--pw-fg-primary); white-space: pre-line; }
.pw-post__text a { color: var(--pw-fg-link); text-decoration: none; }
.pw-post__img { display: block; width: 100%; border-radius: var(--pw-radius-lg); object-fit: cover; background: var(--pw-bg-muted); }
/* Each platform's own picture shape: square on Instagram, a wide link card on
   Facebook, 16:9 on X. The glyph (X) takes the ink; the coloured logos keep
   their own colour. */
.pw-post--x .pw-post__img { aspect-ratio: 16 / 9; }
.pw-post--instagram .pw-post__img { aspect-ratio: 1; }
.pw-post--facebook .pw-post__img { aspect-ratio: 1.91 / 1; }
.pw-post__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-5); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-post__stat { display: inline-flex; align-items: center; gap: var(--pw-space-2); font-variant-numeric: tabular-nums; }
.pw-post__foot a { margin-inline-start: auto; color: var(--pw-fg-link); text-decoration: none; font-weight: var(--pw-font-weight-medium); }
.pw-post__foot a:hover { text-decoration: underline; }
/* Why the assistant chose it -- the line that makes a quoted post trustworthy. */
.pw-media__why { display: flex; align-items: flex-start; gap: var(--pw-space-3); margin: 0; padding-block-start: var(--pw-space-4); border-block-start: 1px solid var(--pw-border-faint); font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-secondary); }
.pw-media__why .pw-icon { flex: none; margin-block-start: 1px; color: var(--pw-tint-ai-fg); }

/* Article */
.pw-article { display: flex; gap: var(--pw-space-6); max-width: 520px; padding: var(--pw-space-6); border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-surface); color: inherit; text-decoration: none; }
.pw-article:hover { border-color: var(--pw-border-default); }
.pw-article__thumb { flex: none; width: 112px; aspect-ratio: 1; border-radius: var(--pw-radius-lg); object-fit: cover; background: var(--pw-bg-muted); }
.pw-article__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--pw-space-2); }
.pw-article__site { display: flex; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-article__site .pw-favicon { width: 16px; height: 16px; }
.pw-article__title { font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-article__excerpt { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pw-article__meta { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
@media (max-width: 560px) { .pw-article__thumb { width: 72px; } }

/* A row of mixed sources, with the system's edge fade. */
.pw-media__rail-wrap { position: relative; width: 100%; min-width: 0; }
.pw-media__rail { display: flex; gap: var(--pw-space-4); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding-block-end: var(--pw-space-1); }
.pw-media__rail::-webkit-scrollbar { display: none; }
.pw-media__rail > * { flex: 0 0 280px; scroll-snap-align: start; }
.pw-media__rail.has-lead  { --pw-fade-lead: 40px; }
.pw-media__rail.has-trail { --pw-fade-trail: 40px; }
.pw-media__rail .pw-vid, .pw-media__rail .pw-post { max-width: none; }
.pw-media__rail .pw-post__text { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.pw-media__privacy { display: flex; align-items: center; gap: var(--pw-space-3); margin: 0; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }

/* -- Answer cards: shared shell ------------------------------------------------------
   Code, files, music, people, weather and places all sit in the same card: a
   hairline, the large radius, the surface, and a quiet foot that says where
   it came from and how to open it there. */
.pw-acard { display: flex; flex-direction: column; gap: var(--pw-space-5); max-width: 560px; margin-block-start: var(--pw-space-5); padding: var(--pw-space-7); border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl); background: var(--pw-bg-surface); }
.pw-acard__head { display: flex; align-items: center; gap: var(--pw-space-5); }
.pw-acard__head > .pw-icon, .pw-acard__head > .pw-brand-glyph, .pw-acard__head > .pw-brand-mark { flex: none; }
.pw-acard__title { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pw-acard__name { font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-acard__sub { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-acard__text { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-acard__stats { display: flex; flex-wrap: wrap; gap: var(--pw-space-3) var(--pw-space-6); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-acard__stats > span { display: inline-flex; align-items: center; gap: var(--pw-space-2); font-variant-numeric: tabular-nums; }
.pw-acard__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-3); padding-block-start: var(--pw-space-5); border-block-start: 1px solid var(--pw-border-faint); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-acard__foot > .pw-btn:first-of-type { margin-inline-start: auto; }
.pw-langdot { width: 10px; height: 10px; border-radius: var(--pw-radius-circle); background: var(--pw-color-brand-500); }

/* GitHub: issues and pull requests as rows with their state in words. */
.pw-ghrows { display: flex; flex-direction: column; }
.pw-ghrow { display: flex; align-items: flex-start; gap: var(--pw-space-4); padding-block: var(--pw-space-4); border-block-start: 1px solid var(--pw-border-faint); color: inherit; text-decoration: none; }
.pw-ghrow:first-child { border-block-start: 0; padding-block-start: 0; }
.pw-ghrow__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pw-ghrow__title { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); }
.pw-ghrow:hover .pw-ghrow__title { color: var(--pw-fg-link); }
.pw-ghrow__meta { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-ghstate { flex: none; display: inline-flex; align-items: center; gap: var(--pw-space-2); padding: 1px var(--pw-space-4); border-radius: var(--pw-radius-pill); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); }
.pw-ghstate--open { background: var(--pw-tint-success-bg); color: var(--pw-tint-success-fg); }
.pw-ghstate--merged { background: var(--pw-tint-ai-bg); color: var(--pw-tint-ai-fg); }
.pw-ghstate--closed { background: var(--pw-tint-danger-bg); color: var(--pw-tint-danger-fg); }

/* A Workspace file with a look inside it. */
.pw-wsprev { border: 1px solid var(--pw-border-faint); border-radius: var(--pw-radius-lg); overflow: hidden; background: var(--pw-bg-subtle); }
.pw-wsprev table { width: 100%; border-collapse: collapse; font-size: var(--pw-text-xs-size); font-variant-numeric: tabular-nums; }
.pw-wsprev th, .pw-wsprev td { padding: var(--pw-space-3) var(--pw-space-5); border-block-end: 1px solid var(--pw-border-faint); text-align: start; color: var(--pw-fg-secondary); }
.pw-wsprev th { background: var(--pw-bg-muted); color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-wsprev td.is-num, .pw-wsprev th.is-num { text-align: end; }
.pw-wsprev tr:last-child td { border-block-end: 0; font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-slides { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--pw-space-3); padding: var(--pw-space-4); }
.pw-slide { position: relative; aspect-ratio: 16 / 9; display: flex; flex-direction: column; justify-content: flex-end; padding: var(--pw-space-3); border-radius: var(--pw-radius-sm); background: var(--pw-bg-surface); box-shadow: 0 0 0 1px var(--pw-border-faint); font-size: 9px; line-height: 1.3; font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); overflow: hidden; }
.pw-slide__n { position: absolute; inset-block-start: 4px; inset-inline-start: 6px; font-size: 9px; color: var(--pw-fg-quaternary); font-weight: var(--pw-font-weight-medium); }
.pw-slide__band { position: absolute; inset-inline: 0; inset-block-start: 0; height: 40%; }
.pw-wsaccess { display: flex; align-items: center; gap: var(--pw-space-3); }

/* Music: tracks, an album, an artist, and where to open them. */
.pw-cover { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: var(--pw-radius-sm); color: var(--pw-color-white); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-bold); overflow: hidden; }
img.pw-cover { object-fit: cover; background: var(--pw-bg-muted); }
.pw-cover--lg { width: 112px; height: 112px; border-radius: var(--pw-radius-md); font-size: var(--pw-text-lg-size); box-shadow: var(--pw-shadow-md); }
.pw-cover--round { border-radius: var(--pw-radius-circle); }
.pw-tracks { display: flex; flex-direction: column; }
.pw-track { display: flex; align-items: center; gap: var(--pw-space-5); padding: var(--pw-space-3) var(--pw-space-2); border-radius: var(--pw-radius-lg); }
.pw-track:hover { background: var(--pw-bg-hover); }
.pw-track__n { flex: none; width: 18px; text-align: center; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-track__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.pw-track__title { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-track.is-playing .pw-track__title { color: var(--pw-fg-brand); }
.pw-track__artist { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-track__time { flex: none; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
/* The preview button carries its own progress ring while it plays. */
.pw-track__play { position: relative; flex: none; }
.pw-track__play::after {
  content: ""; position: absolute; inset: -2px; border-radius: var(--pw-radius-circle); pointer-events: none;
  background: conic-gradient(var(--pw-fg-brand) calc(var(--pw-preview-p, 0) * 1turn), transparent 0);
  /* Only the mask's alpha matters; any opaque token will do. */
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), var(--pw-fg-primary) 0); mask: radial-gradient(farthest-side, transparent calc(100% - 2px), var(--pw-fg-primary) 0);
  opacity: 0;
}
.pw-track.is-playing .pw-track__play::after { opacity: 1; }
.pw-album { display: flex; gap: var(--pw-space-7); }
.pw-album__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--pw-space-2); }
.pw-album__kind { font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary); }
.pw-album__title { font-size: var(--pw-text-lg-size); line-height: var(--pw-text-lg-line); font-weight: var(--pw-font-weight-bold); color: var(--pw-fg-primary); }
.pw-album__by { font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); }
.pw-openin { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-4); }
.pw-openin .pw-segmented { flex: none; }
.pw-openin .pw-brand-mark, .pw-openin .pw-brand-glyph { vertical-align: -3px; }
@media (max-width: 520px) { .pw-album { flex-direction: column; } }

/* People. */
.pw-person__avatar > img { width: 100%; height: 100%; object-fit: cover; }
.pw-person__avatar { flex: none; overflow: hidden; display: grid; place-items: center; width: 64px; height: 64px; border-radius: var(--pw-radius-circle); background: var(--pw-bg-muted); color: var(--pw-fg-secondary); font-size: var(--pw-text-lg-size); font-weight: var(--pw-font-weight-bold); }
.pw-pfacts { display: grid; grid-template-columns: max-content 1fr; gap: var(--pw-space-3) var(--pw-space-7); margin: 0; font-size: var(--pw-text-sm-size); }
.pw-pfacts dt { color: var(--pw-fg-tertiary); }
.pw-pfacts dd { margin: 0; color: var(--pw-fg-primary); }
.pw-timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.pw-timeline li { position: relative; display: flex; gap: var(--pw-space-5); padding-block-end: var(--pw-space-5); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-timeline li::before { content: ""; flex: none; width: 8px; height: 8px; margin-block-start: 6px; border-radius: var(--pw-radius-circle); background: var(--pw-border-strong); }
.pw-timeline li:not(:last-child)::after { content: ""; position: absolute; inset-inline-start: 3.5px; inset-block: 16px 0; width: 1px; background: var(--pw-border-subtle); }
.pw-timeline time { flex: none; width: 64px; color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
/* A card's sources, opened on request. */
.pw-acard__sources { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--pw-space-2); }
.pw-acard__source a { display: flex; align-items: flex-start; gap: var(--pw-space-4); padding: var(--pw-space-3) var(--pw-space-4); border-radius: var(--pw-radius-md); color: inherit; text-decoration: none; transition: background var(--pw-duration-fast) var(--pw-ease-out); }
.pw-acard__source a:hover { background: var(--pw-bg-hover); }
.pw-acard__source.is-lit a { background: var(--pw-bg-selected); }
.pw-acard__source .pw-cite { flex: none; margin: 2px 0 0; }
.pw-acard__source-body { display: flex; flex-direction: column; min-width: 0; font-size: var(--pw-text-sm-size); }
.pw-acard__source-body b { font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); }
.pw-acard__source-body span { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-stances { display: flex; flex-direction: column; gap: var(--pw-space-4); }
.pw-stance { display: grid; grid-template-columns: 120px 1fr; gap: var(--pw-space-5); padding-block-end: var(--pw-space-4); border-block-end: 1px solid var(--pw-border-faint); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); }
.pw-stance:last-child { border-block-end: 0; padding-block-end: 0; }
.pw-stance b { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-stance span { color: var(--pw-fg-secondary); }
@media (max-width: 520px) { .pw-stance { grid-template-columns: 1fr; gap: var(--pw-space-1); } }

/* Weather in a chat. */
.pw-wxc { gap: var(--pw-space-6); }
.pw-wxc__now { display: flex; align-items: center; gap: var(--pw-space-6); }
.pw-wxc__now img { width: 64px; height: 64px; flex: none; }
.pw-wxc__temp { font-size: 44px; line-height: 1; font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); font-variant-numeric: tabular-nums; }
.pw-wxc__cond { display: flex; flex-direction: column; gap: 2px; font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); }
.pw-wxc__cond b { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-wxc__units { margin-inline-start: auto; align-self: flex-start; }
.pw-wxc__hours-wrap { position: relative; min-width: 0; }
.pw-wxc__hours { display: flex; gap: var(--pw-space-3); overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none; padding-block: var(--pw-space-2); }
.pw-wxc__hours.has-lead  { --pw-fade-lead: 40px; }
.pw-wxc__hours.has-trail { --pw-fade-trail: 40px; }
.pw-wxc__hours::-webkit-scrollbar { display: none; }
.pw-wxc__hour { flex: 0 0 76px; scroll-snap-align: start; display: flex; flex-direction: column; align-items: center; gap: var(--pw-space-3); padding-block: var(--pw-space-5); border-radius: var(--pw-radius-lg); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-wxc__hour img { width: 44px; height: 44px; }
.pw-wxc__hour b { font-size: var(--pw-text-sm-size); color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-wxc__hour.is-now { background: var(--pw-bg-subtle); }
.pw-wxc__days { display: flex; flex-direction: column; }
.pw-wxc__day { display: grid; grid-template-columns: 56px 28px 44px 1fr 44px; align-items: center; gap: var(--pw-space-4); padding-block: var(--pw-space-3); border-block-start: 1px solid var(--pw-border-faint); font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); font-variant-numeric: tabular-nums; }
.pw-wxc__day img { width: 28px; height: 28px; }
.pw-wxc__day b { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-medium); }
.pw-wxc__lo { text-align: end; color: var(--pw-fg-tertiary); }
.pw-wxc__range { position: relative; height: 6px; border-radius: var(--pw-radius-pill); background: var(--pw-bg-muted); }
.pw-wxc__range > i { position: absolute; inset-block: 0; border-radius: inherit; background: linear-gradient(to right, var(--pw-color-brand-300), var(--pw-color-warning-400)); }
.pw-wxc__advice { display: flex; gap: var(--pw-space-4); margin: 0; padding: var(--pw-space-5) var(--pw-space-6); border-radius: var(--pw-radius-lg); background: var(--pw-bg-subtle); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-wxc__advice .pw-icon { flex: none; margin-block-start: 3px; color: var(--pw-fg-brand); }

/* Places, side by side, and what matters. */
.pw-cities { display: grid; grid-template-columns: repeat(var(--pw-cities-n, 3), minmax(0, 1fr)); gap: var(--pw-space-4); }
.pw-city { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 1px; aspect-ratio: 4 / 3; padding: var(--pw-space-5); border-radius: var(--pw-radius-lg); overflow: hidden; color: var(--pw-color-white); background: var(--pw-bg-muted); }
.pw-city > img, .pw-city__wash { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pw-city::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, var(--pw-bg-lightbox) 15%, transparent 75%); }
.pw-city__name, .pw-city__country, .pw-city__badge { position: relative; z-index: 1; }
.pw-city__name { font-size: var(--pw-text-md-size); line-height: 1.2; font-weight: var(--pw-font-weight-bold); }
.pw-city__country { font-size: var(--pw-text-xs-size); line-height: 1.3; opacity: .85; }
.pw-city__badge { position: absolute; inset-block-start: var(--pw-space-4); inset-inline-start: var(--pw-space-4); padding: 2px var(--pw-space-4); border-radius: var(--pw-radius-pill); background: var(--pw-bg-surface); color: var(--pw-fg-primary); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); box-shadow: var(--pw-shadow-xs); }
.pw-city__badge[hidden] { display: none; }
/* The row that decides it, for what the reader said matters. */
.pw-compare tr.is-focus th, .pw-compare tr.is-focus td { box-shadow: inset 0 1px 0 var(--pw-border-strong), inset 0 -1px 0 var(--pw-border-strong); }
.pw-compare tr.is-focus th { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-priorities { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }

/* A trip across cities: the route, then each stop. */
.pw-trip { gap: var(--pw-space-6); }
.pw-route { display: flex; align-items: flex-start; overflow-x: auto; scrollbar-width: none; padding-block: var(--pw-space-2); }
.pw-route::-webkit-scrollbar { display: none; }
.pw-route__stop { flex: none; display: flex; flex-direction: column; align-items: center; gap: var(--pw-space-2); width: 96px; text-align: center; }
.pw-route__dot { display: grid; place-items: center; line-height: 1; width: 36px; height: 36px; border-radius: var(--pw-radius-circle); background: var(--pw-action-bg); color: var(--pw-action-fg); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-bold); }
.pw-route__city { font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-route__nights { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-route__leg { flex: 1 0 72px; display: flex; flex-direction: column; align-items: center; gap: var(--pw-space-1); margin-block-start: 8px; font-size: 11px; color: var(--pw-fg-tertiary); text-align: center; }
.pw-route__leg::before { content: ""; align-self: stretch; height: 0; margin-block-end: var(--pw-space-2); border-block-start: 2px dashed var(--pw-border-default); }
.pw-route__leg .pw-icon { color: var(--pw-fg-secondary); }
.pw-stops { display: flex; flex-direction: column; }
/* The route on a map, opened from the card's foot. Flat, like every card in
   an answer: the map is the page, the pins are the only thing lifted. */
.pw-trip__map { margin-block: var(--pw-space-5) 0; border: 1px solid var(--pw-border-subtle); }
.pw-trip__map .pw-amap__map { height: 240px; }
.pw-trip__line { inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.pw-trip__line polyline {
  fill: none; stroke: var(--pw-action-bg); stroke-width: 2; stroke-dasharray: 5 5;
  stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; opacity: .85;
}
.pw-trip__pin { padding-inline-start: 3px; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); cursor: pointer; }
.pw-trip__pin .pw-route__dot { width: 20px; height: 20px; font-size: 11px; line-height: 1; }
.pw-stop { border-radius: var(--pw-radius-md); }
.pw-stop { display: flex; flex-direction: column; gap: var(--pw-space-3); padding-block: var(--pw-space-6); border-block-start: 1px solid var(--pw-border-faint); }
.pw-stop__head { display: flex; align-items: center; gap: var(--pw-space-5); }
.pw-stop__title { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.pw-stop__title b { font-size: var(--pw-text-md-size); color: var(--pw-fg-primary); }
.pw-stop__title span { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-stop__days { list-style: decimal; margin: 0; padding-inline-start: var(--pw-space-10); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-md-line); color: var(--pw-fg-secondary); }
.pw-stop__days li::marker { color: var(--pw-fg-quaternary); font-size: var(--pw-text-xs-size); }
.pw-nights { display: inline-flex; align-items: center; gap: var(--pw-space-2); }
.pw-nights output { min-width: 58px; text-align: center; font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); font-variant-numeric: tabular-nums; }
.pw-budget { display: grid; grid-template-columns: 1fr auto; gap: var(--pw-space-3) var(--pw-space-6); padding: var(--pw-space-6); border-radius: var(--pw-radius-lg); background: var(--pw-bg-subtle); font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); font-variant-numeric: tabular-nums; }
.pw-budget dt, .pw-budget dd { margin: 0; }
.pw-budget dd { text-align: end; color: var(--pw-fg-primary); }
.pw-budget .is-total { padding-block-start: var(--pw-space-3); border-block-start: 1px solid var(--pw-border-subtle); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }

/* -- An ad in the conversation (free plan) --------------------------------------
   On the free plan an answer may be followed by one ad. It sits AFTER the
   answer, never inside it, set apart by hairlines and labelled Ad in words
   -- an ad that could be mistaken for part of the answer is the one thing
   this block must never be. The advertiser, a rail of offers, a menu to ask
   why, hide or report it, and a line saying what the product promises about
   ads: they do not change answers, and they are matched to the chat's topic,
   not to the person. Remove Ads is the way to the paid plan, stated plainly. */
.pw-chatad {
  display: flex; flex-direction: column; gap: var(--pw-space-6);
  margin-inline-start: calc(30px + var(--pw-space-5));
  padding-block: var(--pw-space-8);
  border-block: 1px solid var(--pw-border-subtle);
}
.pw-chatad__head { display: flex; align-items: center; gap: var(--pw-space-4); }
.pw-chatad__logo {
  display: grid; place-items: center; flex: none;
  width: 28px; height: 28px;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-fg-brand); color: var(--pw-fg-inverse);
  font-size: 11px; font-weight: var(--pw-font-weight-bold);
}
.pw-chatad__advertiser {
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); text-decoration: none;
}
.pw-chatad__advertiser:hover { text-decoration: underline; }
.pw-chatad__head .pw-tag { margin-inline-start: auto; }
.pw-chatad__rail-wrap { position: relative; }
.pw-chatad__rail {
  display: flex; gap: var(--pw-space-5);
  overflow-x: auto; scroll-behavior: smooth; scrollbar-width: none;
  scroll-snap-type: x mandatory;
}
.pw-chatad__rail::-webkit-scrollbar { display: none; }
.pw-chatad__rail.has-lead  { --pw-fade-lead: 40px; }
.pw-chatad__rail.has-trail { --pw-fade-trail: 40px; }
.pw-chatad__card {
  flex: 0 0 auto; width: 200px; scroll-snap-align: start;
  display: flex; flex-direction: column;
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  overflow: hidden; color: inherit; text-decoration: none;
  transition: border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-chatad__card:hover { border-color: var(--pw-border-default); }
.pw-chatad__img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: var(--pw-bg-muted); }
.pw-chatad__body { display: flex; flex-direction: column; gap: var(--pw-space-2); padding: var(--pw-space-5) var(--pw-space-6) var(--pw-space-6); }
.pw-chatad__title { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-primary); }
.pw-chatad__price { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); font-variant-numeric: tabular-nums; }
.pw-chatad__price s { margin-inline-start: var(--pw-space-2); font-weight: var(--pw-font-weight-regular); color: var(--pw-fg-tertiary); }
.pw-chatad__nav {
  position: absolute; top: 38%; transform: translateY(-50%);
  display: grid; place-items: center; width: 32px; height: 32px;
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-circle);
  background: var(--pw-bg-surface); color: var(--pw-fg-secondary);
  box-shadow: var(--pw-shadow-md); cursor: pointer;
}
.pw-chatad__nav--next { inset-inline-end: var(--pw-space-3); }
.pw-chatad__nav--prev { inset-inline-start: var(--pw-space-3); }
[dir="rtl"] .pw-chatad__nav svg { transform: scaleX(-1); }
.pw-chatad__note { margin: 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
.pw-chatad__note a { color: var(--pw-fg-secondary); }
/* Hidden: one line where the ad was, with Undo. */
.pw-chatad__hidden { display: none; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-tertiary); }
.pw-chatad.is-hidden { padding-block: var(--pw-space-5); }
.pw-chatad.is-hidden > :not(.pw-chatad__hidden) { display: none; }
.pw-chatad.is-hidden > .pw-chatad__hidden { display: flex; }

/* -- Every kind of ad -----------------------------------------------------------
   One rule set, several shapes. Wherever an ad appears it says Ad in words,
   it offers Why, Hide and Report, and hiding it leaves one line with Undo.
   It never sits inside an answer, never in a Glance, and never looks like a
   source or a citation. Shapes, beyond the carousel:

     .pw-chatad__offer      one product or listing, with its price and a button.
     .pw-chatad__text       a headline, a line of copy, and a few sitelinks.
     .pw-amap__pin--ad      a sponsored place on the answer map, marked Ad.
     .pw-amap__place--ad    its card in the rail, with its own menu.
     .pw-idea--ad           a sponsored idea among the photographs on Maps.

   `.pw-adunit` is any single ad that is not a whole block; it gets the same
   menu and the same hidden line as `.pw-chatad`. */
.pw-chatad__offer {
  display: flex; gap: var(--pw-space-7); align-items: stretch;
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface); overflow: hidden;
}
.pw-chatad__offer-img { flex: none; width: 176px; object-fit: cover; background: var(--pw-bg-muted); }
.pw-chatad__offer-body { display: flex; flex-direction: column; gap: var(--pw-space-3); padding: var(--pw-space-7) var(--pw-space-7) var(--pw-space-7) 0; min-width: 0; }
.pw-chatad__offer-title { margin: 0; font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-chatad__offer-text { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-chatad__offer-foot { display: flex; align-items: center; gap: var(--pw-space-5); margin-top: auto; }
.pw-chatad__offer-foot .pw-btn { margin-inline-start: auto; }
@media (max-width: 560px) {
  .pw-chatad__offer { flex-direction: column; }
  .pw-chatad__offer-img { width: 100%; aspect-ratio: 16 / 9; }
  .pw-chatad__offer-body { padding: 0 var(--pw-space-7) var(--pw-space-7); }
}

.pw-chatad__text { display: flex; flex-direction: column; gap: var(--pw-space-3); }
.pw-chatad__headline { font-size: var(--pw-text-lg-size); line-height: var(--pw-text-lg-line); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-link); text-decoration: none; }
.pw-chatad__headline:hover { text-decoration: underline; }
.pw-chatad__desc { margin: 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-chatad__links { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); margin-top: var(--pw-space-2); }

/* The small ad label that rides on pins, cards and tiles. */
.pw-adlabel {
  display: inline-flex; align-items: center; height: 18px; padding: 0 var(--pw-space-3);
  border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-muted); color: var(--pw-fg-secondary);
  font-size: 10px; font-weight: var(--pw-font-weight-bold); letter-spacing: .02em;
}

/* Map: the sponsored pin names itself Ad before its rating. */
.pw-amap__pin--ad { gap: var(--pw-space-2); padding-inline-start: var(--pw-space-2); }
.pw-amap__pin--ad .pw-adlabel { height: 18px; }
.pw-amap__pin--ad.is-selected .pw-adlabel { background: color-mix(in srgb, var(--pw-bg-surface) 22%, transparent); color: inherit; }
/* Its card: the whole card still chooses the place; the menu sits apart. */
.pw-amap__place--ad { position: relative; padding-inline-end: var(--pw-space-10); }
.pw-amap__place--ad .pw-adlabel { margin-inline-start: var(--pw-space-2); }
.pw-amap__place-menu { position: absolute; top: var(--pw-space-2); inset-inline-end: var(--pw-space-2); }

/* Maps ideas: a sponsored tile is an article -- a link across it and a menu
   on it -- badged in its corner. */
.pw-idea--ad .pw-idea__link { position: absolute; inset: 0; z-index: 1; }
.pw-idea__badge {
  position: absolute; z-index: 2; top: var(--pw-space-5); inset-inline-start: var(--pw-space-5);
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  padding: var(--pw-space-1) var(--pw-space-4);
  border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-lightbox); color: var(--pw-color-white);
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); font-weight: var(--pw-font-weight-semibold);
  pointer-events: none;
}
.pw-idea__menu { position: absolute; z-index: 2; top: var(--pw-space-4); inset-inline-end: var(--pw-space-4); }
.pw-idea__menu > .pw-btn { background: var(--pw-bg-lightbox); color: var(--pw-color-white); border-color: transparent; }

/* Hidden, for any single ad unit: the unit keeps its footprint and says so. */
.pw-adunit__hidden {
  display: none; position: absolute; inset: 0; z-index: 3;
  flex-direction: column; align-items: center; justify-content: center; gap: var(--pw-space-2);
  padding: var(--pw-space-5); text-align: center;
  border-radius: inherit; background: var(--pw-bg-subtle);
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
}
.pw-adunit.is-hidden > .pw-adunit__hidden { display: flex; }
.pw-adunit.is-hidden { box-shadow: none; }

/* -- Words arriving ---------------------------------------------------------
   New text in a response clears from a blur, word by word, as it arrives --
   see WORDS ARRIVING in pw-components.js for what is wrapped and when. Opacity
   and blur only: no movement, so a line never shifts while it is being read,
   and inline spans keep the paragraph's own wrapping and kerning. Blocks that
   must not assemble piecemeal arrive whole with the same curve. */
/* GSAP runs this (WORDS ARRIVING in pw-components.js). The keyframe is the
   fallback the controller applies as `.pw-arrive` only when the motion layer
   is not loaded -- same curve, same length. */
.pw-arrive { animation: pw-word-in 380ms var(--pw-ease-out) both; }
@keyframes pw-word-in { from { opacity: 0; filter: blur(6px); } }

/* The person's own message is a bubble on the trailing edge; the assistant's is
   plain text on the page. Bubbling both halves makes long answers unreadable. */
.pw-msg--user { justify-content: flex-end; }
.pw-msg--user .pw-msg__body {
  flex: 0 1 auto;
  max-width: 78%;
  padding: var(--pw-space-5) var(--pw-space-7);
  border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-muted);
  font-size: var(--pw-text-sm-size);
  line-height: var(--pw-text-md-line);
}
.pw-msg--assistant .pw-msg__body { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-lg-line); color: var(--pw-fg-secondary); }
.pw-msg--assistant .pw-msg__body strong { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }

/* -- What the answer cost, folded away --------------------------------------
   An assistant that searched the web, read three pages and thought for six
   seconds has done something the reader is entitled to know about, and nothing
   they want to read every time. Folded, it is one quiet line; opened, it is the
   list. It is the system's accordion with a smaller voice -- composition, not a
   second accordion. */
.pw-work { margin-block-end: var(--pw-space-6); font-size: var(--pw-text-xs-size); }
.pw-work .pw-accordion__trigger {
  gap: var(--pw-space-4);
  padding: var(--pw-space-3) 0;
  font-size: var(--pw-text-xs-size);
  /* Its own line, not the answer's 28px: 6 + 18 + 6 makes the row exactly the
     avatar's 30, so the line sits on the orb's centre instead of 5px below. */
  line-height: var(--pw-text-xs-line);
  font-weight: var(--pw-font-weight-medium);
  color: var(--pw-fg-tertiary);
}
.pw-work .pw-accordion__trigger:hover { color: var(--pw-fg-secondary); }
/* The flush accordion gives its caret a disc and sends it to the far edge,
   because a list of questions has nothing else saying a row opens. Here the
   line already says it -- so the caret shrinks back to a mark that follows the
   sentence, sitting next to the seconds rather than across the message. */
.pw-work .pw-accordion__caret {
  width: var(--pw-icon-xs); height: var(--pw-icon-xs); flex: none;
  margin-inline-start: 0;
  border-radius: 0;
  background: none;
  color: var(--pw-fg-quaternary);
}
.pw-work .pw-accordion__trigger:hover .pw-accordion__caret { background: none; color: var(--pw-fg-tertiary); }
.pw-work .pw-accordion__panel { padding: 0 0 var(--pw-space-4) var(--pw-space-8); }
.pw-work__step {
  display: flex; align-items: flex-start; gap: var(--pw-space-4);
  padding-block: var(--pw-space-2);
  color: var(--pw-fg-tertiary);
}
.pw-work__step .pw-icon { flex: none; margin-block-start: 2px; color: var(--pw-fg-quaternary); }
/* A step that is still running says so by moving; one that is done says so by
   being a tick. Nothing here is a percentage, because none of it is measurable
   and a bar that lies is worse than a spinner that does not. */
.pw-work__step.is-active { color: var(--pw-fg-secondary); }

/* -- The actions under an answer --------------------------------------------
   Always present, never loud. Revealing them on hover is the common move and
   it is wrong twice: there is no hover on a phone, and an answer whose controls
   appear only when pointed at is an answer you cannot tell is rateable. Ghost
   buttons at `--sm` carry it -- quiet until wanted, and the same size as every
   other icon-only control in the system. */
.pw-msg__actions {
  display: flex; align-items: center; gap: var(--pw-space-2);
  margin-block-start: var(--pw-space-6);
}
.pw-msg__actions--split { justify-content: space-between; }
.pw-msg__actions .pw-btn--icon { color: var(--pw-fg-tertiary); }
.pw-msg__actions .pw-btn--icon:hover { color: var(--pw-fg-primary); }
/* Voted. The pressed thumb keeps the brand and its partner goes quiet, because
   the pair is one answer to one question and showing both as live afterwards
   invites the reader to wonder whether it took. */
.pw-msg__actions .pw-btn[aria-pressed="true"] { color: var(--pw-fg-brand); }

/* -- Stopped, failed, refused -----------------------------------------------
   Three different things and the reader can tell them apart at a glance, which
   is the whole job: stopped is neutral because they did it, failed is danger
   because the service did it, refused is neither -- it is an answer, just not
   the one asked for, and dressing it as an error would say the product broke
   when it did exactly what it was built to do. */
.pw-msg__status {
  display: flex; align-items: center; gap: var(--pw-space-4);
  margin-block-start: var(--pw-space-5);
  font-size: var(--pw-text-sm-size);
  color: var(--pw-fg-tertiary);
}
.pw-msg__status--error { color: var(--pw-fg-danger); }
/* The gap above a status is from the answer it ends. When the status IS the
   answer -- a failure before any text arrived -- there is nothing to be apart
   from, and the margin would drop it 10px below the orb. */
.pw-msg__body > .pw-msg__status:first-child { margin-block-start: 0; }
.pw-msg__status .pw-icon { flex: none; }

/* -- A generated image ------------------------------------------------------
   Its own actions, because they are about the picture and not about the
   sentence that produced it: download, and try again. */
.pw-msg__figure {
  margin-block-start: var(--pw-space-6);
  max-width: 420px;
}
.pw-msg__figure img {
  display: block; width: 100%;
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-muted);
}
.pw-msg__figure figcaption {
  margin-block-start: var(--pw-space-4);
  font-size: var(--pw-text-xs-size);
  color: var(--pw-fg-tertiary);
}

/* -- Code -------------------------------------------------------------------
   The block follows the theme: a white card with a hairline in light, a dark
   one in dark -- code is part of the answer, and a black slab in a white
   thread is the loudest thing on the page. Every colour in it is one of the
   `--pw-code-*` values below, set once per theme, syntax included. */
.pw-code, .pw-diff {
  --pw-code-bg: var(--pw-bg-surface);
  --pw-code-fg: var(--pw-fg-primary);
  --pw-code-muted: var(--pw-fg-tertiary);
  --pw-code-rule: var(--pw-border-faint);
  --pw-code-hover: var(--pw-bg-hover);
  --pw-code-gutter: var(--pw-fg-quaternary);
  --pw-code-k: var(--pw-color-brand-600);
  --pw-code-s: var(--pw-color-success-650);
  --pw-code-n: var(--pw-color-warning-600);
  --pw-code-c: var(--pw-color-gray-500);
  --pw-code-f: var(--pw-color-purple-600);
  --pw-code-add: color-mix(in srgb, var(--pw-color-success-500) 12%, transparent);
  --pw-code-del: color-mix(in srgb, var(--pw-color-danger-500) 10%, transparent);
}
.pw-code {
  margin-block: var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-code-bg);
  overflow: hidden;
}
[data-pw-theme="dark"] :is(.pw-code, .pw-diff),
html.dark :is(.pw-code, .pw-diff) {
  --pw-code-bg: var(--pw-color-gray-950);
  --pw-code-fg: color-mix(in srgb, var(--pw-fg-on-overlay) 92%, transparent);
  --pw-code-muted: color-mix(in srgb, var(--pw-fg-on-overlay) 62%, transparent);
  --pw-code-rule: color-mix(in srgb, var(--pw-fg-on-overlay) 12%, transparent);
  --pw-code-hover: var(--pw-bg-on-overlay);
  --pw-code-gutter: color-mix(in srgb, var(--pw-fg-on-overlay) 32%, transparent);
  --pw-code-k: var(--pw-color-brand-300);
  --pw-code-s: var(--pw-color-success-300);
  --pw-code-n: var(--pw-color-warning-400);
  --pw-code-c: var(--pw-color-gray-500);
  --pw-code-f: var(--pw-color-danger-250);
  --pw-code-add: color-mix(in srgb, var(--pw-color-success-500) 22%, transparent);
  --pw-code-del: color-mix(in srgb, var(--pw-color-danger-500) 22%, transparent);
}
@media (prefers-color-scheme: dark) {
  html:not(.light):not(.dark) :is(.pw-code, .pw-diff) {
    --pw-code-bg: var(--pw-color-gray-950);
    --pw-code-fg: color-mix(in srgb, var(--pw-fg-on-overlay) 92%, transparent);
    --pw-code-muted: color-mix(in srgb, var(--pw-fg-on-overlay) 62%, transparent);
    --pw-code-rule: color-mix(in srgb, var(--pw-fg-on-overlay) 12%, transparent);
    --pw-code-hover: var(--pw-bg-on-overlay);
    --pw-code-gutter: color-mix(in srgb, var(--pw-fg-on-overlay) 32%, transparent);
    --pw-code-k: var(--pw-color-brand-300);
    --pw-code-s: var(--pw-color-success-300);
    --pw-code-n: var(--pw-color-warning-400);
    --pw-code-c: var(--pw-color-gray-500);
    --pw-code-f: var(--pw-color-danger-250);
    --pw-code-add: color-mix(in srgb, var(--pw-color-success-500) 22%, transparent);
    --pw-code-del: color-mix(in srgb, var(--pw-color-danger-500) 22%, transparent);
  }
}
.pw-code__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--pw-space-5);
  padding: var(--pw-space-4) var(--pw-space-4) var(--pw-space-4) var(--pw-space-7);
  border-block-end: 1px solid var(--pw-code-rule);
  font-size: var(--pw-text-xs-size);
  color: var(--pw-code-muted);
}
.pw-code__head .pw-btn { color: var(--pw-code-muted); }
.pw-code__head .pw-btn:hover { background: var(--pw-code-hover); color: var(--pw-code-fg); }
.pw-code pre {
  margin: 0;
  padding: var(--pw-space-7);
  overflow-x: auto;
  color: var(--pw-code-fg);
  font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--pw-text-xs-size);
  line-height: var(--pw-text-lg-line);
  tab-size: 2;
}
/* The head: language or filename first, then the block's own tools. */
.pw-code__name { display: inline-flex; align-items: center; gap: var(--pw-space-3); min-width: 0; margin-inline-end: auto; }
.pw-code__name .pw-icon { flex: none; }
.pw-code__name b { font-weight: var(--pw-font-weight-semibold); color: var(--pw-code-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-code__tools { display: flex; gap: var(--pw-space-1); }
.pw-code__head .pw-btn[aria-pressed="true"] { background: var(--pw-code-hover); color: var(--pw-code-fg); }
/* Scrolls sideways, with the system's edge fade when there is more. */
.pw-code__body { position: relative; }
.pw-code.is-wrapped pre { white-space: pre-wrap; overflow-wrap: anywhere; }
.pw-code pre.has-more { --pw-fade-trail: 40px; }
/* Line numbers: every line is a span, counted in the gutter. */
.pw-code__line { display: block; min-height: 1lh; }
.pw-code--lines pre { counter-reset: pw-line; padding-inline-start: var(--pw-space-5); }
.pw-code--lines .pw-code__line::before {
  counter-increment: pw-line; content: counter(pw-line);
  display: inline-block; width: 3ch; margin-inline-end: var(--pw-space-6);
  text-align: end; color: var(--pw-code-gutter);
  user-select: none;
}
/* A change, as a change: added and removed lines tinted, the sign kept. */
.pw-code__line--add { background: var(--pw-code-add); }
.pw-code--diff pre { padding-inline: 0; }
.pw-code--diff .pw-code__line { padding-inline: var(--pw-space-7); }
.pw-code__line--del { background: var(--pw-code-del); }
/* Syntax: a few families, each with a value per theme. */
.pw-tok-k { color: var(--pw-code-k); }
.pw-tok-s { color: var(--pw-code-s); }
.pw-tok-n { color: var(--pw-code-n); }
.pw-tok-c { color: var(--pw-code-c); font-style: italic; }
.pw-tok-f { color: var(--pw-code-f); }
/* Long: held at a height with a fade and "Show all", never a hard cut. */
.pw-code.is-folded pre { max-height: calc(var(--pw-code-rows, 14) * 1lh + var(--pw-space-7)); overflow-y: hidden; }
/* The fade is the block's own colour rising over the last lines, so it needs
   no mask and no colour of its own. */
.pw-code__more { position: relative; }
.pw-code.is-folded .pw-code__more::before {
  content: ""; position: absolute; inset-inline: 0; inset-block-end: 100%; height: 64px;
  background: linear-gradient(to bottom, transparent, var(--pw-code-bg));
  pointer-events: none;
}
.pw-code__more {
  display: flex; align-items: center; justify-content: center; gap: var(--pw-space-3);
  width: 100%; padding: var(--pw-space-4);
  border: 0; border-block-start: 1px solid var(--pw-code-rule);
  background: transparent; color: var(--pw-code-muted);
  font: inherit; font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); cursor: pointer;
}
.pw-code__more:hover { color: var(--pw-code-fg); background: var(--pw-code-hover); }
.pw-code:not(.is-folded) .pw-code__more .pw-icon { transform: rotate(180deg); }

/* Code inside a sentence. */
.pw-msg__body :not(pre) > code {
  padding: 1px 5px; border-radius: var(--pw-radius-xs);
  background: var(--pw-bg-muted); color: var(--pw-fg-primary);
  font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: .9em;
}

/* -- What the person attached ------------------------------------------------
   In their own bubble, above their words, in the shape the composer used. A
   file that arrives as a line of text in the message loses the fact that it was
   a file. */
.pw-msg__files { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); margin-block-end: var(--pw-space-4); }
.pw-msg__file {
  display: inline-flex; align-items: center; gap: var(--pw-space-3);
  max-width: 100%;
  padding: var(--pw-space-2) var(--pw-space-5) var(--pw-space-2) var(--pw-space-3);
  border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-surface);
  font-size: var(--pw-text-xs-size);
  color: var(--pw-fg-secondary);
}
.pw-msg__file span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-msg__file .pw-icon { flex: none; color: var(--pw-fg-quaternary); }
/* Changed after the fact. Said in the message rather than in a toast, because a
   toast is gone by the time anyone scrolls back to work out why the answer
   above does not match the question below it. */
.pw-msg__edited { margin-inline-start: var(--pw-space-3); font-size: var(--pw-text-xs-size); color: var(--pw-fg-quaternary); }

/* -- Where the answer is coming from ----------------------------------------
   A project's files are invisible context, and invisible context is the thing
   people distrust most about an assistant. One line, at the top of the answer
   that used them. */
.pw-msg__context {
  display: inline-flex; align-items: center; gap: var(--pw-space-3);
  margin-block-end: var(--pw-space-5);
  padding: var(--pw-space-2) var(--pw-space-5);
  border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-muted);
  font-size: var(--pw-text-xs-size);
  line-height: var(--pw-text-xs-line);
  color: var(--pw-fg-secondary);
}
/* 2 + 4 + 18 + 4 puts the pill's line on the orb's centre (15px). */
.pw-msg__body > .pw-msg__context:first-child { margin-block-start: var(--pw-space-1); }
.pw-msg__context .pw-icon { color: var(--pw-fg-quaternary); }
/* A second source line, after the prose about the first. */
.pw-msg__body > :not(.pw-msg__context) + .pw-msg__context { margin-block-start: var(--pw-space-6); }

/* -- The day it was said ----------------------------------------------------- */
.pw-thread__day {
  display: flex; align-items: center; gap: var(--pw-space-6);
  font-size: var(--pw-text-xs-size);
  font-weight: var(--pw-font-weight-semibold);
  color: var(--pw-fg-tertiary);
}
.pw-thread__day::before, .pw-thread__day::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--pw-border-faint);
}

/* -- Follow-ups --------------------------------------------------------------
   Offered under the answer, never above the composer: they belong to the thing
   that was just said, and a rail pinned over the field would make them look
   like part of what you are about to say. */
.pw-followups { margin-block-start: var(--pw-space-6); }

/* Streaming has no caret. Words arrive with the blur reveal (WORDS ARRIVING in
   pw-components.js), and the orb says the answer is still being written; a
   blinking block on top of both was a third signal for the same fact. */

/* -----------------------------------------------------------------------------
   CITATIONS
   Every factual claim carries a numbered source. An AI answer without visible
   provenance is the one thing this product cannot ship.
   ----------------------------------------------------------------------------- */
.pw-cite {
  display: inline-grid; place-items: center;
  min-width: 17px; height: 17px; padding-inline: 4px;
  margin-inline-start: 3px;
  border-radius: var(--pw-radius-sm);
  background: var(--pw-bg-selected);
  color: var(--pw-fg-brand);
  font-size: 10px;
  /* ITS OWN, and that is the whole of what was wrong with it. A badge with a
     fixed height cannot inherit a line-height in PIXELS: the paragraph's 28px
     came down here and became the height of the line box holding the digit, so
     a 28px box was centred in a 17px one -- the digit hung 4px out of the badge
     below, and the grid's synthesized baseline, which is taken from that box,
     floated the whole badge about 6px above the text it belongs to. It read as
     a superscript that had lost its footing.

     Measured against the cap band of the 14px text it sits in: the badge's
     centre was 5.9px high before and is 0.4px low now, and the digit stands 1px
     from the top of the badge and 1.5 from the bottom -- the half-pixel is the
     font's own descent, which is what centring a digit optically looks like. */
  line-height: 1;
  font-weight: var(--pw-font-weight-bold);
  vertical-align: 2px;
  cursor: pointer;
}
.pw-cite:hover { background: var(--pw-color-brand-100); }
/* A NAMED citation: the source's mark and name in a quiet pill, and "+2" when
   the sentence stands on more than one. For answers read by people who want to
   know WHO said it at a glance, not look it up. Same preview, same wiring as
   the number: `href` names the first source, `data-pw-cites` the rest. */
.pw-cite--named {
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  height: 20px; min-width: 0; padding: 0 var(--pw-space-3) 0 3px;
  margin-inline-start: var(--pw-space-2);
  border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-muted); color: var(--pw-fg-secondary);
  font-size: 11px; font-weight: var(--pw-font-weight-medium);
  text-decoration: none; white-space: nowrap; vertical-align: 1px;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-cite--named:hover { background: color-mix(in srgb, var(--pw-fg-primary) 12%, var(--pw-bg-muted)); color: var(--pw-fg-primary); }
.pw-cite--named .pw-favicon { width: 14px; height: 14px; border: 0; border-radius: var(--pw-radius-circle); background: var(--pw-bg-surface); color: var(--pw-fg-tertiary); }
.pw-cite--named .pw-favicon .pw-icon { width: 10px; height: 10px; }
.pw-cite__more { color: var(--pw-fg-tertiary); }
.pw-cite--named[aria-expanded="true"] { background: var(--pw-fg-primary); color: var(--pw-bg-surface); }
.pw-cite--named[aria-expanded="true"] .pw-cite__more { color: inherit; opacity: .7; }
.pw-cite--named[aria-expanded="true"] .pw-favicon { background: color-mix(in srgb, var(--pw-bg-surface) 22%, transparent); color: var(--pw-bg-surface); }
.pw-sources { display: flex; gap: var(--pw-space-4); overflow-x: auto; scrollbar-width: none; margin-top: var(--pw-space-6); }
/* The row runs off the card's edge as often as not. A card sliced by the edge
   reads as a bug; the same card fading reads as "keep going" -- so the edge
   with more to show fades, and a chevron on it scrolls. The controller wraps
   each row in a rail and drives both through the system's edge scroller. */
.pw-sources-rail { position: relative; margin-top: var(--pw-space-6); }
/* One fade for every scrolling row in the AI module -- the sources rail and
   the comparison table -- sized per component below. */
.pw-sources-rail > .pw-sources, .pw-compare[data-pw-scroller], .pw-amap__rail, .pw-chatad__rail, .pw-media__rail, .pw-wxc__hours, .pw-code pre {
  --pw-fade-start: transparent 0, #000 var(--pw-fade-lead, 0px);
  --pw-fade-end: #000 calc(100% - var(--pw-fade-trail, 0px)), transparent 100%;
  -webkit-mask-image: linear-gradient(to right, var(--pw-fade-start), var(--pw-fade-end));
  mask-image: linear-gradient(to right, var(--pw-fade-start), var(--pw-fade-end));
}
.pw-sources-rail > .pw-sources { margin-top: 0; scroll-behavior: smooth; }
.pw-sources-rail > .pw-sources.has-lead  { --pw-fade-lead: 48px; }
.pw-sources-rail > .pw-sources.has-trail { --pw-fade-trail: 48px; }
.pw-sources-rail__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-circle);
  background: var(--pw-bg-surface);
  color: var(--pw-fg-secondary);
  box-shadow: var(--pw-shadow-md);
  cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-sources-rail__nav:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-sources-rail__nav--next { inset-inline-end: 0; }
.pw-sources-rail__nav--prev { inset-inline-start: 0; }
[dir="rtl"] .pw-sources-rail__nav svg { transform: scaleX(-1); }
.pw-sources::-webkit-scrollbar { display: none; }
.pw-source {
  flex: 0 0 auto; width: 176px;
  padding: var(--pw-space-5);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  text-align: start;
}
.pw-source__head { display: flex; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-source__title { margin-top: var(--pw-space-3); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }

/* -- Checking a claim ---------------------------------------------------------
   A citation is a promise that the sentence came from somewhere. The badge
   alone asks the reader to take that on trust; the preview lets them check it
   without leaving: the site, the page, and the passage the claim was drawn
   from, quoted. Hover or focus shows it, a press pins it (the only way on
   touch), and while it is open the claim and its source card are marked, so
   the eye can see which words the passage is standing behind.

   The source carries what the preview shows -- `data-pw-quote`, and
   optionally `data-pw-date` and `data-pw-site` -- and the badge points at it
   with `href="#id"`. One source of truth: the row of cards, the preview and the
   All sources drawer are all read from the same element.

   `.pw-citation` is the block both the preview and the drawer list use. */
.pw-citation { display: flex; flex-direction: column; gap: var(--pw-space-3); min-width: 0; }
.pw-citation__head {
  display: flex; align-items: center; gap: var(--pw-space-3);
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  color: var(--pw-fg-tertiary);
}
.pw-citation__head .pw-cite { margin-inline-start: auto; vertical-align: 0; }
.pw-citation__title {
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
  text-decoration: none;
}
a.pw-citation__title:hover { text-decoration: underline; }
/* The passage, quoted -- marked with the AI tint because it is the part the
   answer leaned on, and clamped so a long one cannot turn the preview into the
   page it came from. */
.pw-citation__quote {
  margin: 0; padding-inline-start: var(--pw-space-5);
  border-inline-start: 2px solid var(--pw-tint-ai-fg);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  color: var(--pw-fg-secondary);
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.pw-citation__link {
  display: inline-flex; align-items: center; gap: var(--pw-space-2); align-self: flex-start;
  font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold);
  color: var(--pw-fg-brand); text-decoration: none;
}
.pw-citation__link:hover { text-decoration: underline; }

.pw-cite-preview { width: 320px; padding: var(--pw-space-6); }
.pw-citation__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--pw-space-4); }
.pw-citation__pager { display: flex; align-items: center; gap: var(--pw-space-1); }
.pw-citation__count { min-width: 40px; text-align: center; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
[dir="rtl"] .pw-citation__pager .pw-icon { transform: scaleX(-1); }
/* The badge whose preview is open, and what it stands behind. */
.pw-cite[aria-expanded="true"] { background: var(--pw-action-bg); color: var(--pw-action-fg); }
.pw-claim { border-radius: 3px; -webkit-box-decoration-break: clone; box-decoration-break: clone; transition: background-color var(--pw-duration-fast) var(--pw-ease-out); }
.pw-claim.is-cited { background: color-mix(in srgb, var(--pw-tint-ai-fg) 14%, transparent); }
.pw-source { transition: border-color var(--pw-duration-fast) var(--pw-ease-out); }
.pw-source.is-cited { border-color: var(--pw-tint-ai-fg); }

/* The last card in the row opens the whole list. It says how many there are,
   because "More" invites a guess and a number does not. */
.pw-source--all {
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--pw-space-3);
  width: auto; min-width: 112px;
  font: inherit; color: var(--pw-fg-primary); cursor: pointer;
}
.pw-source--all:hover { background: var(--pw-bg-hover); }
.pw-source__stack { display: flex; }
/* Each disc is solid, so the ring that separates it from the one beneath
   cuts that disc's edge and not the glyph inside it. */
.pw-source__stack .pw-favicon { border-radius: var(--pw-radius-circle); background: var(--pw-bg-muted); box-shadow: 0 0 0 2px var(--pw-bg-surface); }
.pw-source__stack .pw-favicon + .pw-favicon { margin-inline-start: -5px; }
.pw-source__count { font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); }

/* -- Answers that are not prose ---------------------------------------------
   What the BUILDING state produces: an answer whose shape is part of the
   answer. Four shapes, each for one kind of question --

     .pw-keyfacts   "how much, how long, how many": the numbers, each labelled.
     .pw-compare    "which one": the options side by side on the same rows.
     .pw-proscons   "should I": what speaks for it and what against, apart.
     .pw-steps      "how do I": in the order they are done.

   Prose still carries the reasoning around them. A block without a sentence
   before it is a table that fell out of the sky; one sentence saying what it
   shows is enough. Every value can carry its own citation. */

/* Key facts: the figure first and large, what it is underneath. Tiles and not
   rows, because these are read at a glance and compared by eye, not scanned. */
.pw-keyfacts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: var(--pw-space-4);
  margin-block: var(--pw-space-5);
}
.pw-keyfact {
  display: flex; flex-direction: column; gap: var(--pw-space-1);
  padding: var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-keyfact__value {
  font-size: var(--pw-text-xl-size); line-height: var(--pw-text-xl-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
  font-variant-numeric: tabular-nums;
}
.pw-keyfact__label { font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }

/* Comparison: the options are the columns and the criteria are the rows, so
   reading across a row compares like with like. The best value on each row is
   marked -- tinted and ticked -- so the table answers "which one" without the
   reader doing the arithmetic. The criterion column stays put while the
   options scroll. */
.pw-compare { margin-block: var(--pw-space-5); }
.pw-compare .pw-table thead th { background: var(--pw-bg-subtle); }
.pw-compare .pw-table tbody tr:hover td { background: none; }
.pw-compare .pw-table tbody th {
  padding: var(--pw-space-5) var(--pw-space-6);
  border-bottom: 1px solid var(--pw-border-subtle);
  font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-tertiary);
  text-align: start; white-space: nowrap;
}
.pw-compare .pw-table tbody tr:last-child th { border-bottom: 0; }
.pw-compare .pw-table td { padding: var(--pw-space-5) var(--pw-space-6); color: var(--pw-fg-primary); white-space: nowrap; }
/* Wider than its column, the options scroll under the criteria -- and the
   edge with more to show fades rather than cutting a column in half, the same
   rule as the sources row. `data-pw-scroller` on the wrap drives it. */
.pw-compare.has-trail { --pw-fade-trail: 40px; }
.pw-compare.has-lead { --pw-fade-lead: 40px; }
.pw-compare .pw-table :is(thead th:first-child, tbody th) {
  position: sticky; inset-inline-start: 0; z-index: 1;
  background: var(--pw-bg-surface);
}
.pw-compare .pw-table thead th:first-child { background: var(--pw-bg-subtle); }
.pw-compare .pw-table td.is-best {
  background: var(--pw-tint-success-bg);
  color: var(--pw-tint-success-fg);
  font-weight: var(--pw-font-weight-semibold);
}
.pw-compare .pw-table td.is-best::before {
  content: ""; display: inline-block; width: 14px; height: 14px;
  margin-inline-end: var(--pw-space-2); vertical-align: -2px;
  background: currentColor;
  -webkit-mask: var(--pw-compare-tick) center / contain no-repeat;
  mask: var(--pw-compare-tick) center / contain no-repeat;
}
.pw-compare { --pw-compare-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
/* What the table does not show: the note under it, not a footnote marker. */
.pw-compare__note { margin: var(--pw-space-3) 0 0; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }

/* Pros and cons: two lists, never interleaved -- a reader weighing a decision
   wants each side whole. Side by side when there is room, stacked when not. */
.pw-proscons {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--pw-space-4);
  margin-block: var(--pw-space-5);
}
.pw-proscons__side {
  padding: var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-proscons__title {
  display: flex; align-items: center; gap: var(--pw-space-3);
  margin: 0 0 var(--pw-space-4);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-proscons__title .pw-icon {
  display: grid; place-items: center; flex: none;
  width: 20px; height: 20px; padding: 3px;
  border-radius: var(--pw-radius-circle);
}
.pw-proscons__side--pro .pw-proscons__title .pw-icon { background: var(--pw-tint-success-bg); color: var(--pw-tint-success-fg); }
.pw-proscons__side--con .pw-proscons__title .pw-icon { background: var(--pw-bg-muted); color: var(--pw-fg-secondary); }
.pw-proscons ul { margin: 0; padding-inline-start: var(--pw-space-8); display: flex; flex-direction: column; gap: var(--pw-space-3); }
.pw-proscons li { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-proscons li::marker { color: var(--pw-fg-quaternary); }

/* Steps: numbered, joined by a line, each a title and what it involves. The
   line says "then"; the numbers let a reader say "step 3" out loud. */
.pw-steps { list-style: none; margin: var(--pw-space-5) 0; padding: 0; counter-reset: pw-step; }
.pw-steps > li {
  position: relative; counter-increment: pw-step;
  display: grid; grid-template-columns: 24px 1fr; column-gap: var(--pw-space-6);
  padding-bottom: var(--pw-space-7);
}
.pw-steps > li:last-child { padding-bottom: 0; }
.pw-steps > li::before {
  content: counter(pw-step);
  grid-row: 1 / span 2;
  display: grid; place-items: center;
  width: 24px; height: 24px;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-tint-ai-bg); color: var(--pw-tint-ai-fg);
  font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-bold);
  font-variant-numeric: tabular-nums;
}
.pw-steps > li:not(:last-child)::after {
  content: ""; position: absolute;
  inset-inline-start: 11.5px; top: 28px; bottom: 4px;
  width: 1px; background: var(--pw-border-subtle);
}
.pw-steps__title {
  font-size: var(--pw-text-sm-size); line-height: 24px;
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-steps__detail { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }

/* -- A question back --------------------------------------------------------
   When a query is ambiguous the honest move is to ask rather than guess, and
   the kind move is to make the answer a tap. One question, the likely answers
   as chips, a way to say something else, and a way to decline -- "Use Best
   Guess" -- because being asked must never be a wall. Once answered it folds
   to one line that says what was chosen and can be changed, so the thread
   keeps a record of what the answer below it depends on.

   It is the body of the WAITING state, in a message whose orb is ringed --
   in a conversation only. A Glance answers the words that were searched and
   never asks back; a question about what someone meant belongs in a chat they
   can answer it in. One question at a time; a second one waits for the first. */
.pw-ask {
  display: flex; flex-direction: column; gap: var(--pw-space-5);
  margin-block: var(--pw-space-2) var(--pw-space-4);
  padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-ask__question {
  margin: 0;
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line);
  font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary);
}
.pw-ask__hint {
  margin: calc(var(--pw-space-3) * -1) 0 0;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary);
}
.pw-ask__options { display: flex; flex-wrap: wrap; gap: var(--pw-space-3); }
.pw-ask__other { max-width: 280px; }  /* an answer, not an essay */
.pw-ask__actions { display: flex; align-items: center; gap: var(--pw-space-3); }
/* Answered: one line, what was chosen, and the way back. */
.pw-ask__answer {
  display: none; align-items: center; gap: var(--pw-space-3);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary);
}
.pw-ask__answer .pw-icon { flex: none; color: var(--pw-fg-success); }
.pw-ask__answer strong { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-ask__answer .pw-btn { margin-inline-start: auto; }
.pw-ask.is-answered { padding: var(--pw-space-4) var(--pw-space-4) var(--pw-space-4) var(--pw-space-6); background: var(--pw-bg-subtle); }
.pw-ask.is-answered > :not(.pw-ask__answer) { display: none; }
.pw-ask.is-answered > .pw-ask__answer { display: flex; }

/* The drawer's list: numbered, quoted, in the order the answer cites them. */
.pw-source-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.pw-source-list > li { padding-block: var(--pw-space-7); border-top: 1px solid var(--pw-border-subtle); }
.pw-source-list > li:first-child { padding-top: 0; border-top: 0; }

/* -----------------------------------------------------------------------------
   COMPOSER
   ----------------------------------------------------------------------------- */
/* TWO ROWS, NOT ONE. What you are saying goes on top, and everything that
   qualifies how it will be answered -- attachments, tools, the model's limits --
   sits under it in a band of its own. One row was right while the composer was a
   text box with a send button; it stops being right the moment the controls
   outnumber the words, and a tool the reader has turned on has to stay visible
   while they type the sentence it applies to.

   The band is `--pw-bg-muted` and not `--pw-bg-subtle`: the ramp inverts, so
   muted is darker than the surface in light and lighter in dark, which is a band
   in both. Subtle resolves to the CANVAS in dark -- the composer would have had
   a hole in the bottom of it. */
.pw-composer {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--pw-field-border);
  border-radius: var(--pw-radius-2xl);
  background: var(--pw-field-bg);
  box-shadow: var(--pw-shadow-sm);
  transition: border-color var(--pw-duration-fast) var(--pw-ease-out), box-shadow var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-composer:focus-within { border-color: var(--pw-field-border-focus); box-shadow: var(--pw-focus-ring); }

.pw-composer__input {
  width: 100%;
  min-height: 24px;
  /* Three lines, then it scrolls. A composer that grows without end walks the
     page out from under the thread it belongs to; one capped at a single line
     hides what is being sent. Three is where a prompt stops being a sentence
     and starts being a document, and the cap is expressed in `lh` so it
     survives a change of type scale. The controller measures `scrollHeight`
     against this, so the number lives in one place. */
  max-height: 4.5lh;
  padding: var(--pw-space-7) var(--pw-space-8) var(--pw-space-5);
  border: 0; background: transparent; resize: none; outline: none;
  overflow-y: auto;
  color: var(--pw-field-fg);
  font-family: inherit;
  font-size: var(--pw-text-md-size);
  line-height: var(--pw-text-md-line);
}
.pw-composer__input::placeholder { color: var(--pw-field-placeholder); }

/* -- The controls -----------------------------------------------------------
   ONE SURFACE. The tinted band under the field made the composer two objects
   stacked -- a box to type in, and a tray of buttons beneath it -- when it is
   one control with a row of settings on its floor. Nothing separates them now
   except the space between them: the field is where the words are, the row
   beneath is what they will be sent with, and neither needs a line to say so.

   The corners are kept as a rounding, not a fill: they are what any future
   state that DOES take a colour (an error, a drop target) will meet the
   composer's own stroke with. */
.pw-composer__bar {
  display: flex; align-items: center; gap: var(--pw-space-4);
  padding: var(--pw-space-2) var(--pw-space-4) var(--pw-space-4) var(--pw-space-5);
  border-end-start-radius: calc(var(--pw-radius-2xl) - 1px);
  border-end-end-radius: calc(var(--pw-radius-2xl) - 1px);
  background: transparent;
}
/* One voice for every labelled control in the bar -- Tools, effort, the tool
   chips, the model -- the model's: body size, medium weight. A bold button, a
   small semibold chip and a regular dropdown side by side read as three kinds
   of thing when they are all the same kind: a setting for this message. */
.pw-composer__bar :is(.pw-btn:not(.pw-btn--icon), .pw-chip) {
  font-size: var(--pw-text-sm-size);
  font-weight: var(--pw-font-weight-medium);
}
.pw-composer__bar .pw-chip { height: 32px; }
/* GHOST, all of them. Attach, Tools, effort, a tool that is on -- every control
   on the composer's floor sits on the surface with no fill, and takes one on
   hover or while its menu is open. Filled pills in a row made the settings
   louder than the words being written above them. Selected still goes to the
   neutral inverse, so on and off stay two steps apart. */
.pw-composer__bar :is(.pw-btn--tertiary, .pw-btn--ghost, .pw-chip--soft) {
  box-shadow: none;
  background: transparent;
}
.pw-composer__bar :is(.pw-btn--tertiary, .pw-btn--ghost, .pw-chip--soft):is(:hover, [aria-expanded="true"]) {
  background: var(--pw-bg-hover);
}
.pw-composer .pw-chip--soft[aria-pressed="true"],
.pw-composer .pw-chip--soft.is-selected,
.pw-composer .pw-chip--soft.is-current { background: var(--pw-bg-inverse); }
/* The chips take the room and give it back: they scroll rather than wrapping,
   because a composer that grows a second row of tools moves the thing you are
   typing into. The send button is outside this, so it never scrolls away. */
.pw-composer__tools {
  display: flex; align-items: center; gap: var(--pw-space-3);
  flex: 1 1 auto; min-width: 0;
  overflow-x: auto;
  /* A rail that scrolls SIDEWAYS must not scroll down, and `overflow-x: auto`
     alone makes the other axis `auto` too -- `clip` is not available here
     either, since beside a scrolling axis it computes to `hidden`. So the axis
     is taken away by hand, and the overhang that made it scrollable in the
     first place is gone from the chip's dismiss. */
  overflow-y: hidden;
  scrollbar-width: none;
}
.pw-composer__tools::-webkit-scrollbar { display: none; }
.pw-composer__actions { display: flex; align-items: center; gap: var(--pw-space-3); flex: 0 0 auto; margin-inline-start: auto; }
/* A hairline between what the composer IS and what it will DO. The plus and the
   tools button open things; everything after the rule is the state they left
   behind -- so with nothing switched on there is nothing on the far side of it,
   and a divider with one side empty is not dividing anything. It is drawn only
   while a chip is there to be divided from, which the row can answer for
   itself: a tool that is off is `hidden`, so "is any tool on" is "has this row
   a child that is not hidden". No controller has to remember to tell it. */
.pw-composer__sep {
  display: none;
  flex: 0 0 auto; align-self: stretch;
  width: 1px; margin-inline: var(--pw-space-2);
  background: var(--pw-border-subtle);
}
.pw-composer__bar:has(.pw-composer__tools > :not([hidden]):not(.pw-composer__cmd)) .pw-composer__sep { display: block; }

/* -- Slash commands ----------------------------------------------------------
   `/image`, `/ratio`, `/style`, typed in the field. The pickers they open have
   no chip to hang from: each hangs from a point at the composer's top-start
   corner, so it opens above the field the way the command list does. */
.pw-composer { position: relative; }
.pw-composer__cmd { position: absolute; inset-block-start: 0; inset-inline-start: var(--pw-space-6); width: 0; height: 0; }
.pw-composer__cmd-anchor { position: absolute; inset: 0; display: block; width: 0; height: 0; pointer-events: none; }
.pw-slash { width: 300px; padding: var(--pw-space-2); }
.pw-slash .pw-select__option-title { font-family: var(--pw-font-mono, ui-monospace, monospace); }
/* The mode, as its own row above the text. Ghost, like the controls under the
   field: the name in the brand colour, because it is the one thing in the box
   that is not your words, and each setting a quiet button that takes a fill on
   hover and opens its own picker -- the same picker its slash command opens. */
.pw-composer__mode {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0;
  min-height: 24px;
  padding: var(--pw-space-5) var(--pw-space-6) 0 var(--pw-space-8);
  font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-medium);
  white-space: nowrap;
}
.pw-composer__mode + .pw-composer__input { padding-block-start: var(--pw-space-3); }
.pw-composer__mode-label { display: inline-flex; align-items: center; height: 100%; padding-inline: 0 var(--pw-space-2); color: var(--pw-action-bg); }
.pw-composer__mode > .pw-icon { margin-inline-end: var(--pw-space-2); color: var(--pw-action-bg); }
.pw-composer__mode-meta { display: inline-flex; align-items: center; height: 100%; }
.pw-composer__mode-part,
.pw-composer__mode-x {
  display: inline-flex; align-items: center; height: 24px; padding: 0 var(--pw-space-2);
  border: 0; border-radius: var(--pw-radius-sm); background: transparent;
  color: var(--pw-fg-tertiary); font: inherit; cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-composer__mode-dot { color: var(--pw-fg-quaternary); }
.pw-composer__mode-x { width: 24px; justify-content: center; padding: 0; color: var(--pw-fg-quaternary); }
.pw-composer__mode-part:hover,
.pw-composer__mode-x:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }

/* -- Context meter ------------------------------------------------------------
   Beside Send: a ring for how full this chat's context is, and a panel with
   the rest -- the context window by kind, the plan's limits, and from 80% an
   offer to compact. Ghost like the rest of the bar. */
.pw-meter {
  flex: none; display: grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: var(--pw-radius-circle);
  background: transparent; cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-meter:is(:hover, [aria-expanded="true"]) { background: var(--pw-bg-hover); }
.pw-meter svg { width: 18px; height: 18px; transform: rotate(-90deg); overflow: visible; }
.pw-meter circle { fill: none; stroke-width: 2.5; }
.pw-meter .is-track { stroke: var(--pw-bg-strong); }
.pw-meter .is-fill { stroke: var(--pw-action-bg); stroke-linecap: round; transition: stroke var(--pw-duration-base) var(--pw-ease-out); }
.pw-meter.is-high .is-fill { stroke: var(--pw-tint-warning-fg); }
.pw-meter.is-full .is-fill { stroke: var(--pw-fg-danger); }

.pw-usagepop { width: 340px; padding: 0; }
.pw-usagepop__section { display: flex; flex-direction: column; gap: var(--pw-space-4); padding: var(--pw-space-7) var(--pw-space-8); }
.pw-usagepop__section + .pw-usagepop__section { border-block-start: 1px solid var(--pw-border-subtle); }
.pw-usagepop__row { display: flex; align-items: baseline; gap: var(--pw-space-4); font-size: var(--pw-text-sm-size); }
.pw-usagepop__name { flex: 1; min-width: 0; color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-medium); }
.pw-usagepop__value { color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pw-usagepop__value b { margin-inline-start: var(--pw-space-3); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-secondary); }
.pw-usagepop__head { display: flex; align-items: center; font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary); }
.pw-usagepop__head .pw-btn { margin-inline-start: auto; }
.pw-usagepop__stack { display: flex; gap: 2px; height: 6px; border-radius: var(--pw-radius-pill); background: var(--pw-bg-strong); overflow: hidden; }
.pw-usagepop__stack > i { flex: none; width: 0; height: 100%; }
.pw-usagepop__stack > [data-kind="messages"] { background: var(--pw-action-bg); }
.pw-usagepop__stack > [data-kind="files"] { background: var(--pw-color-info-500); }
.pw-usagepop__stack > [data-kind="tools"] { background: var(--pw-color-warning-500); }
.pw-usagepop__stack > [data-kind="instructions"] { background: var(--pw-fg-quaternary); }
.pw-usagepop.is-high :is(.pw-usagepop__stack > [data-kind="messages"], .pw-usagepop__legend [data-kind="messages"]) { background: var(--pw-tint-warning-fg); }
.pw-usagepop__legend { display: flex; flex-wrap: wrap; gap: var(--pw-space-2) var(--pw-space-6); margin: 0; padding: 0; list-style: none; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-usagepop__legend li { display: inline-flex; align-items: center; gap: var(--pw-space-2); }
.pw-usagepop__legend i { width: 6px; height: 6px; border-radius: var(--pw-radius-circle); }
.pw-usagepop__legend [data-kind="messages"] { background: var(--pw-action-bg); }
.pw-usagepop__legend [data-kind="files"] { background: var(--pw-color-info-500); }
.pw-usagepop__legend [data-kind="tools"] { background: var(--pw-color-warning-500); }
.pw-usagepop__legend [data-kind="instructions"] { background: var(--pw-fg-quaternary); }
.pw-usagepop__limit { display: flex; flex-direction: column; gap: var(--pw-space-3); }
.pw-usagepop__compact {
  display: flex; flex-direction: column; gap: var(--pw-space-4);
  margin-block-start: var(--pw-space-2); padding: var(--pw-space-5) var(--pw-space-6);
  border-radius: var(--pw-radius-lg); background: var(--pw-tint-warning-bg);
  font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary);
}
.pw-usagepop__compact[hidden] { display: none; }
.pw-usagepop__compact p { margin: 0; }
.pw-usagepop__compact strong { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-usagepop__compact .pw-btn { align-self: flex-start; }
.pw-usagepop__foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--pw-space-6) var(--pw-space-8); border-block-start: 1px solid var(--pw-border-subtle);
  font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); text-decoration: none;
  border-end-start-radius: inherit; border-end-end-radius: inherit;
}
.pw-usagepop__foot:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }

/* -- Attachments ------------------------------------------------------------
   Above the text, because the file is context for the sentence and the sentence
   is usually written about it. Each one owns its own state: a spinner while the
   service reads it, then the size. */
.pw-composer__files {
  display: flex; flex-wrap: wrap; gap: var(--pw-space-4);
  padding: var(--pw-space-7) var(--pw-space-8) 0;
}
.pw-attach {
  position: relative;
  display: flex; align-items: center; gap: var(--pw-space-4);
  max-width: 240px;
  padding: var(--pw-space-4) var(--pw-space-6) var(--pw-space-4) var(--pw-space-4);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-muted);
}
.pw-attach__body { min-width: 0; }
.pw-attach__name {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--pw-text-xs-size);
  font-weight: var(--pw-font-weight-semibold);
  color: var(--pw-fg-primary);
}
.pw-attach__note { display: block; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
/* On the corner rather than in the row: the row is the file, and a control
   inside it competes with the name for the width the name needs. */
.pw-attach__remove {
  position: absolute; inset-block-start: -8px; inset-inline-end: -8px;
  display: grid; place-items: center;
  width: 24px; height: 24px;
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-circle);
  background: var(--pw-bg-surface);
  box-shadow: var(--pw-shadow-xs);
  color: var(--pw-fg-secondary);
  cursor: pointer;
}
/* A bigger hit area than the disc, so the corner is easy to press. */
.pw-attach__remove::after { content: ""; position: absolute; inset: -8px; }
.pw-attach__remove .pw-icon { width: 14px; height: 14px; }
.pw-attach__remove:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-attach .pw-filerow__mark { width: 32px; height: 32px; }
.pw-attach__thumb { flex: none; width: 32px; height: 32px; overflow: hidden; border-radius: var(--pw-radius-sm); background: var(--pw-bg-subtle); }
.pw-attach__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Uploading: a hairline filling along the bottom edge, and the note counting. */
.pw-attach { overflow: visible; }
.pw-attach__bar {
  position: absolute; inset-inline: var(--pw-space-4); inset-block-end: 3px; height: 2px;
  border-radius: var(--pw-radius-pill);
  background: linear-gradient(to right, var(--pw-fg-brand) calc(var(--pw-attach-p, 0) * 100%), var(--pw-border-subtle) 0);
  opacity: 0; transition: opacity var(--pw-duration-fast) var(--pw-ease-out);
}
[dir="rtl"] .pw-attach__bar { transform: scaleX(-1); }
.pw-attach.is-busy .pw-attach__bar { opacity: 1; }
.pw-attach.is-busy .pw-attach__name { color: var(--pw-fg-secondary); }
/* Refused: the card stays long enough to say why, and goes when removed. */
.pw-attach.is-error { background: var(--pw-tint-danger-bg); }
.pw-attach.is-error .pw-attach__note { color: var(--pw-fg-danger); }
.pw-composer__files[hidden] { display: none; }
/* A file held over the composer: the whole box says it will take it. */
.pw-composer.is-dropping { outline: 2px dashed var(--pw-border-brand); outline-offset: -2px; background: var(--pw-bg-selected); }

/* The person's images, in the thread: above their words, like the files. */
.pw-msg__images { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--pw-space-3); }
.pw-msg--user.has-photo .pw-msg__images img { display: block; width: 120px; aspect-ratio: 1; object-fit: cover; border-radius: var(--pw-radius-lg); background: var(--pw-bg-muted); }
.pw-msg--user.has-photo > .pw-msg__files { margin: 0; justify-content: flex-end; }
.pw-msg--user.has-photo > .pw-msg__files .pw-msg__file { background: var(--pw-bg-muted); }

/* -- Pointing at part of an image -------------------------------------------
   An answer about a picture can mark the part it means: a numbered box on the
   image and the same number in the text. Pointing at either lights both, so
   "the crack here" is never a guess about where. */
.pw-lookat { position: relative; margin: var(--pw-space-6) 0 0; max-width: 420px; }
.pw-lookat img { display: block; width: 100%; border-radius: var(--pw-radius-lg); background: var(--pw-bg-muted); }
.pw-lookat__box {
  position: absolute;
  border: 2px solid var(--pw-color-white);
  border-radius: var(--pw-radius-md);
  box-shadow: 0 0 0 1px var(--pw-bg-lightbox), var(--pw-shadow-md);
  transition: box-shadow var(--pw-duration-fast) var(--pw-ease-out), border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-lookat__box::before {
  content: attr(data-n);
  position: absolute; inset-block-start: -10px; inset-inline-start: -10px;
  display: grid; place-items: center; width: 20px; height: 20px;
  border-radius: var(--pw-radius-circle);
  background: var(--pw-fg-brand); color: var(--pw-color-white);
  font-size: 11px; font-weight: var(--pw-font-weight-bold); line-height: 1;
}
.pw-lookat__box.is-lit { border-color: var(--pw-fg-brand); box-shadow: 0 0 0 4px color-mix(in srgb, var(--pw-fg-brand) 30%, transparent), var(--pw-shadow-md); }
.pw-lookat__ref {
  display: inline-grid; place-items: center;
  min-width: 18px; height: 18px; padding: 0 4px; margin-inline: 2px;
  border: 0; border-radius: var(--pw-radius-circle);
  background: var(--pw-fg-brand); color: var(--pw-color-white);
  font: inherit; font-size: 11px; font-weight: var(--pw-font-weight-bold); line-height: 1;
  vertical-align: 1px; cursor: pointer;
}
.pw-lookat__ref:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: 2px; }

/* -- Refused before it is sent ----------------------------------------------
   The notice is INSIDE the composer, sharing its top corners, because it is
   about this box and not about the page: a banner floating above a composer
   that still looks ready to take a prompt says the trouble is somewhere else.
   The field below it stays filled and stays readable -- a limit is a wait, not
   a reason to throw away what someone wrote. */
.pw-composer__notice {
  display: flex; align-items: center; justify-content: center; gap: var(--pw-space-4);
  padding: var(--pw-space-5) var(--pw-space-8);
  border-start-start-radius: calc(var(--pw-radius-2xl) - 1px);
  border-start-end-radius: calc(var(--pw-radius-2xl) - 1px);
  background: var(--pw-tint-danger-bg);
  color: var(--pw-tint-danger-fg);
  font-size: var(--pw-text-sm-size);
  font-weight: var(--pw-font-weight-semibold);
  text-align: center;
}
/* The quiet kind: few left, not none. Said once, in the same place, without
   alarm -- and with the way to more, as a link rather than a banner. */
.pw-composer__notice--quiet {
  justify-content: flex-start; text-align: start;
  background: var(--pw-bg-subtle); color: var(--pw-fg-secondary);
  font-weight: var(--pw-font-weight-medium);
}
.pw-composer__notice--quiet > .pw-icon { color: var(--pw-fg-tertiary); }
.pw-composer__notice .pw-btn { margin-inline-start: auto; flex: none; }
.pw-composer__notice--quiet .pw-usage-dots { display: inline-flex; gap: 3px; }
.pw-usage-dots > i { width: 6px; height: 6px; border-radius: var(--pw-radius-circle); background: var(--pw-border-default); }
.pw-usage-dots > i.is-left { background: var(--pw-fg-brand); }
.pw-composer.is-blocked { border-color: var(--pw-border-danger); }
.pw-composer.is-blocked .pw-composer__input { color: var(--pw-fg-tertiary); }

/* -- Over the character limit ------------------------------------------------
   The count only appears when it is nearly news. A counter that runs from the
   first keystroke asks every prompt to be measured; one that arrives at 90%
   says the same thing once, at the only moment it matters. */
.pw-composer .pw-char-count {
  flex: 0 0 auto;
  font-size: var(--pw-text-xs-size);
  font-variant-numeric: tabular-nums;
  color: var(--pw-fg-tertiary);
}
/* The number that broke it, and not the limit it broke. Colouring the whole
   string red says the limit is the problem; colouring the count says the count
   is, which is the half the writer can do something about. Beaten here by
   source order rather than specificity -- this file loads after the components
   -- so the over state is restated rather than inherited. */
.pw-composer .pw-char-count.is-over b { color: var(--pw-fg-danger); }
.pw-composer.is-over { border-color: var(--pw-border-danger); }
.pw-composer.is-over:focus-within { box-shadow: 0 0 0 4px var(--pw-tint-danger-bg); }

.pw-disclaimer { margin-top: var(--pw-space-4); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); text-align: center; }

/* -- The dock ----------------------------------------------------------------
   The composer, its disclaimer, and the column they share. It declares the
   container so the composer can answer its own width rather than the viewport's:
   this box is 768px under a thread, 640 on a home screen and 343 on a phone, and
   only one of those three is the viewport. */
.pw-composer-dock {
  container-type: inline-size;
  width: 100%;
  max-width: 768px;
  margin-inline: auto;
}

/* -- Narrow: the labels go, the controls stay --------------------------------
   Every tool keeps its place and loses its word. An overflow menu would have
   been the other answer and it is the wrong one here: these are modes the
   prompt is being written IN, and a mode you cannot see is a mode you will
   forget you turned on. The icon carries it, and the name is in the tooltip
   and the `aria-label`, which is where a name for a glyph belongs. */
@container (max-width: 560px) {
  .pw-composer__label { display: none; }
  .pw-composer__model .pw-composer__label { display: inline; }
  .pw-composer__bar .pw-chip { padding-inline: var(--pw-space-4); }
  .pw-composer__bar .pw-btn--sm { padding-inline: var(--pw-space-4); }
}
/* Phone width: the model picker leaves the field. At this size it lives in
   the chat's header, and the field keeps what is about this message --
   attach, effort, voice, the context ring, send. */
@container (max-width: 400px) {
  .pw-composer__bar [data-pw-menu-root]:has(> .pw-composer__model) { display: none; }
}

/* -----------------------------------------------------------------------------
   INLINE ANSWER  —  "Glance" above the web results
   ----------------------------------------------------------------------------- */
/* The one surface in the product that is written by a model. At rest it is
   a plain card -- the page's surface inside a neutral hairline -- so a
   finished answer reads as content, not as a banner. The AI colour is the
   mark's and the title's, and the edge glow's while it works. The edge is a border-box gradient behind
   a padding-box fill, so it stays a true 1px line at any radius. Every value
   is a token, so dark mode needs no rule here. */
.pw-glance {
  position: relative;
  isolation: isolate;
  padding: var(--pw-space-8);
  border: 1px solid transparent;
  border-radius: var(--pw-radius-xl);
  background:
    linear-gradient(var(--pw-bg-surface), var(--pw-bg-surface)) padding-box,
    linear-gradient(var(--pw-border-subtle), var(--pw-border-subtle)) border-box;
}
[dir="rtl"] .pw-glance {
  background:
    linear-gradient(var(--pw-bg-surface), var(--pw-bg-surface)) padding-box,
    linear-gradient(var(--pw-border-subtle), var(--pw-border-subtle)) border-box;
}
/* While it works, a glow travels the inside of the edge: a short arc of the
   mesh's cyan, red and amber that fades in from nothing and back out, so it never rings
   the whole card, and falls off softly toward the middle so it never sits on
   the text. The arc is a conic gradient turned by `--pw-glance-turn`; the band
   is two soft linear masks, across and down. The controller turns it with
   GSAP and fades it with `--pw-glance-glow`, so the card eases back to
   neutral when the answer lands. Reduced motion keeps the arc still. */
.pw-glance::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: var(--pw-glance-glow, 0);
  background: conic-gradient(from var(--pw-glance-turn, 0deg) at 50% 50%,
    transparent 0deg,
    color-mix(in srgb, var(--pw-ai-mesh-a) 30%, transparent) 45deg,
    color-mix(in srgb, var(--pw-ai-mesh-b) 22%, transparent) 85deg,
    color-mix(in srgb, var(--pw-ai-mesh-c) 30%, transparent) 120deg,
    transparent 165deg,
    transparent 360deg);
  -webkit-mask:
    linear-gradient(to right,  var(--pw-fg-primary), transparent 28px, transparent calc(100% - 28px), var(--pw-fg-primary)),
    linear-gradient(to bottom, var(--pw-fg-primary), transparent 20px, transparent calc(100% - 20px), var(--pw-fg-primary));
  mask:
    linear-gradient(to right,  var(--pw-fg-primary), transparent 28px, transparent calc(100% - 28px), var(--pw-fg-primary)),
    linear-gradient(to bottom, var(--pw-fg-primary), transparent 20px, transparent calc(100% - 20px), var(--pw-fg-primary));
}
/* A failed answer takes the colour off. It keeps the card, so the page does not
   jump, but not the glow: an error dressed in the working colours reads as a
   Glance that is still going. */
.pw-glance[data-state="error"] {
  background:
    linear-gradient(var(--pw-bg-surface), var(--pw-bg-surface)) padding-box,
    linear-gradient(var(--pw-glance-error-edge), var(--pw-glance-error-edge)) border-box;
  /* Softer than a full danger border: the body text and the mark already say
     it failed, and a third full-strength red would shout. */
  --pw-glance-error-edge: color-mix(in srgb, var(--pw-border-danger) 55%, transparent);
}
.pw-glance__head { display: flex; align-items: center; gap: var(--pw-space-4); margin-bottom: var(--pw-space-5); }
/* The name in the mesh, pulled a quarter toward the text colour so the amber
   end still reads on a light page. */
.pw-glance__title {
  font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-bold);
  color: var(--pw-fg-primary);
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--pw-ai-mesh-a) 75%, var(--pw-fg-primary)),
    color-mix(in srgb, var(--pw-ai-mesh-b) 75%, var(--pw-fg-primary)) 55%,
    color-mix(in srgb, var(--pw-ai-mesh-c) 70%, var(--pw-fg-primary)));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.pw-glance__body { font-size: var(--pw-text-sm-size); line-height: var(--pw-text-lg-line); color: var(--pw-fg-secondary); }

/* -- A Glance that is still working ------------------------------------------
   The product sets one attribute, `data-state` on `.pw-glance`, and the card
   follows: the mark takes the same state, the body shows it, and a
   `.pw-sr-only` status says it to a screen reader. No visible words -- the
   answer area is where the reader is already looking, so that is where the
   state is shown.

     thinking    three lines, shimmering. Nothing to read yet.
     building    a small grid assembling cell by cell: a structured answer.
     generating  the answer as it arrives, each word blurring in.
     standby, error: the body as the product wrote it, still.

   There is no waiting. A Glance answers the search and does not ask back --
   clarifying questions live in the chat that "Ask a follow-up" opens.

   The placeholder is injected by the controller. Sources and the actions row
   wait for the answer: there is nothing to cite, copy or rate until it is
   whole. Under reduced motion the lines are still, the grid is built, and the
   words simply appear -- three different pictures, so nothing depends on movement. */
.pw-glance__placeholder { display: none; }
.pw-glance:is([data-state="thinking"], [data-state="building"]) .pw-glance__placeholder { display: block; padding-block: 6px; }
.pw-glance:is([data-state="thinking"], [data-state="building"]) .pw-glance__body { display: none; }
.pw-glance:is([data-state="thinking"], [data-state="building"], [data-state="generating"], [data-state="error"]) :is(.pw-sources, .pw-glance__foot) { display: none; }

.pw-glance__lines, .pw-glance__cells { display: none; }
.pw-glance[data-state="thinking"] .pw-glance__lines { display: grid; gap: 10px; }
.pw-glance[data-state="building"] .pw-glance__cells { display: grid; grid-template-columns: 1.6fr 1fr .7fr; gap: 8px 10px; }

.pw-glance__line, .pw-glance__cell {
  display: block; height: 10px;
  border-radius: var(--pw-radius-pill);
}
/* The system's skeleton shimmer, neutral: the colour while a Glance works is
   the edge glow's, so the lines stay grey. */
.pw-glance__line {
  background: linear-gradient(90deg, var(--pw-skeleton-base) 25%, var(--pw-skeleton-sheen) 37%, var(--pw-skeleton-base) 63%);
  background-size: 400% 100%;
  animation: pw-shimmer 1.4s ease infinite;
}
.pw-glance__line:nth-child(2) { width: 92%; }
.pw-glance__line:nth-child(3) { width: 56%; }
/* Each cell grows from its leading edge in turn, holds, and is rebuilt on the
   next pass. The resting frame -- and the reduced-motion one -- is the whole
   grid built. */
.pw-glance__cell {
  background: var(--pw-skeleton-base);
  transform-origin: left center;
  animation: pw-glance-build 2.2s var(--pw-ease-out) infinite both;
  animation-delay: calc(var(--i) * 110ms);
}
[dir="rtl"] .pw-glance__cell { transform-origin: right center; }
.pw-glance__cell:nth-child(3n + 1) { background: var(--pw-skeleton-sheen); }
@keyframes pw-glance-build {
  0%        { transform: scaleX(0); opacity: 0; }
  30%, 100% { transform: scaleX(1); opacity: 1; }
}

.pw-glance[data-state="error"] .pw-glance__body { color: var(--pw-fg-danger); }
.pw-glance__foot { display: flex; align-items: center; gap: var(--pw-space-4); margin-top: var(--pw-space-6); }

/* =============================================================================
   APP SHELL  —  the AI product's own chrome
   Search is a page; this is an application. The difference that matters is
   that a conversation has a HISTORY, and history has to be reachable without
   leaving what you are in the middle of — which is a sidebar, and is why this
   is the one surface in the system that does not use the search chrome.
   ============================================================================= */
.pw-appshell {
  display: grid;
  /* THE TWO WIDTHS ARE NAMED, and `--pw-aside-width` is the live one. The
     collapse controller tweens that single variable between them, so the
     numbers stay in the stylesheet where the rest of the layout can see them
     and the JavaScript only has to know which two to read. */
  --pw-aside-wide: 272px;
  --pw-aside-rail: 64px;
  --pw-aside-width: var(--pw-aside-wide);
  /* `auto`, with the width on the ASIDE. The column cannot be sized from
     inside a container query -- an element is never its own container, so
     `@container { .pw-appshell { ... } }` asks the PAGE how wide it is and
     silently does nothing. That is exactly what happened: on a phone the shell
     kept a 272px sidebar and squeezed the conversation into what was left,
     one word per line, while the labels inside it correctly disappeared
     (those rules target descendants, which the shell does contain). */
  grid-template-columns: auto minmax(0, 1fr);
  position: relative;   /* the drawer and its scrim are placed against this */
  height: 100%;
  min-height: 0;
  background: var(--pw-bg-surface);
  /* The shell is the container everything inside it answers to. A panel beside
     a thread is 272 of 1200 on a laptop and 272 of 1920 on a desktop, and the
     thread's own measure is what changes -- not the viewport's. */
  container-type: inline-size;
}
/* Collapsed, the rail keeps the controls that are always true -- the mark, the
   new chat, the library -- and drops the list, which is the part that needs
   words. A rail of unlabelled chat titles is a rail of identical glyphs. */
.pw-appshell.is-collapsed { --pw-aside-width: var(--pw-aside-rail); }
/* The rail's rules are written twice -- once for the class the toggle sets,
   once for the container query that narrows the shell on its own -- because a
   rule set cannot be shared across an at-rule boundary. The alternative was to
   make the aside its own size container and query that, which would work today
   and quietly break the first menu anyone puts in the sidebar: `container-type`
   brings layout containment, and a contained element becomes the containing
   block for the fixed-position layer an anchored menu turns into. */
.pw-appshell.is-collapsed .pw-sidenav__item span,
.pw-appshell.is-collapsed .pw-sidenav__end,
.pw-appshell.is-collapsed .pw-sidenav__label,
.pw-appshell.is-collapsed .pw-sidenav__scroll { display: none; }
/* The lockup needs `!important` to leave, because the half of it that belongs
   to this theme is held visible by `.only-light`/`.only-dark`, which are
   themselves `!important` -- and an `!important` is the only thing that
   outranks one. Third documented case in the system, and for the same reason as
   the other two: a rule nothing should be able to win against. */
.pw-appshell.is-collapsed .pw-sidenav__logo { display: none !important; }
.pw-appshell.is-collapsed .pw-sidenav__item { justify-content: center; padding-inline: 0; }
.pw-appshell.is-collapsed .pw-sidenav__pair { flex-direction: column; }
/* The pair shrink-wraps its two rows when they sit side by side; stacked in a
   rail that leaves two 16px targets in a 40px column. A row in the rail is a
   row. */
.pw-appshell.is-collapsed .pw-sidenav__pair .pw-sidenav__item { width: 100%; }
/* With the mark gone the toggle is the only thing left in the head, and a
   control pushed to the end of a 40px box is a control off centre. */
.pw-appshell.is-collapsed .pw-sidenav__head { justify-content: center; }
.pw-appshell.is-collapsed .pw-sidenav__head .pw-btn { margin-inline: auto; }

.pw-appshell__aside {
  display: flex; flex-direction: column;
  width: var(--pw-aside-width);
  min-height: 0;
  padding: var(--pw-space-8) var(--pw-space-6);
  border-inline-end: 1px solid var(--pw-border-faint);
  background: var(--pw-skeleton-base);
}
.pw-appshell__main {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  position: relative;
}
/* The bar floats over the conversation rather than sitting above it. What is in
   it -- a personalisation switch, a chat's own menu -- is about the thread, and
   a full-width bar would put a horizon between the reader and the thing they
   are reading. */
.pw-appshell__bar {
  position: absolute; inset-block-start: 0; inset-inline: 0;
  z-index: var(--pw-z-sticky);
  display: flex; align-items: center; justify-content: flex-end; gap: var(--pw-space-4);
  padding: var(--pw-space-7) var(--pw-space-8);
  pointer-events: none;
}
.pw-appshell__bar > * { pointer-events: auto; }
/* The drawer's handle. It lives in the floating bar, before everything else,
   and is the one control in the shell that is absent until it is needed. */
.pw-appshell__menu { display: none; margin-inline-end: auto; }
.pw-appshell__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* The docked composer and the disclaimer, held at the bottom of the main
   column. Padding rather than a border, because the thread scrolls under it
   and a rule would cut the last line of an answer in half. */
.pw-appshell__dock { flex: 0 0 auto; padding: var(--pw-space-6) var(--pw-space-8) var(--pw-space-7); }

/* -- The sidebar's own parts ------------------------------------------------- */
.pw-sidenav__head {
  display: flex; align-items: center; gap: var(--pw-space-4);
  min-height: 36px;
  margin-block-end: var(--pw-space-8);
}
.pw-sidenav__logo { display: block; height: 22px; width: auto; }
/* A control after the mark goes to the far edge (the collapse toggle). One
   before it (Back) leads the row and the mark follows it: pushing Back to the
   end took the mark with it, and the whole head sat on the right. */
.pw-sidenav__head > :not(:first-child).pw-btn { margin-inline-start: auto; }

/* The nav TAKES THE FREE SPACE, which is what pins the footer to the bottom of
   the rail. Left to its content height the list ended wherever it ended and
   Support, Privacy and Settings followed it up the panel, floating in the
   middle with the rest of the sidebar empty underneath them. They are the
   things that are always there; they belong at the edge that is always there
   too. The space goes to the scrolling list inside, so it is also the part that
   grows when the window does. */
.pw-sidenav { display: flex; flex-direction: column; gap: var(--pw-space-2); min-height: 0; flex: 1 1 auto; }
/* One row shape for every destination in here: a chat, a project, Settings. A
   sidebar whose links are three different objects reads as three sidebars. */
.pw-sidenav__item {
  display: flex; align-items: center; gap: var(--pw-space-5);
  width: 100%;
  /* ONE HEIGHT, whatever the row is carrying. Padding on the block axis made
     the height a function of the contents, so a row with a menu button in it
     stood 48px against its neighbours' 36 -- and because the menu appears on
     the current row, the OPEN chat was permanently taller than the ones around
     it. A row that changes size when you point at it is a list that moves
     under the pointer. The min-height is the row, and the 32px control sits
     inside it with room to spare. */
  min-height: 36px;
  padding: 0 var(--pw-space-5);
  border: 0;
  border-radius: var(--pw-radius-lg);
  background: transparent;
  color: var(--pw-fg-secondary);
  font-size: var(--pw-text-sm-size);
  font-weight: var(--pw-font-weight-medium);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}
.pw-sidenav__item:hover { background: var(--pw-ink-hover); color: var(--pw-fg-primary); }
.pw-sidenav__item > .pw-icon { flex: none; color: var(--pw-fg-tertiary); }
.pw-sidenav__item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Selected is a raised card, not a tint: the sidebar's own ground is already a
   tint, and a tint on a tint is a smudge. The shadow is what says "this one is
   in front", which is exactly what being the open chat means. */
.pw-sidenav__item.is-current {
  background: var(--pw-bg-surface);
  box-shadow: var(--pw-shadow-xs);
  color: var(--pw-fg-primary);
  font-weight: var(--pw-font-weight-semibold);
}
.pw-sidenav__item--brand { color: var(--pw-fg-brand); font-weight: var(--pw-font-weight-semibold); }
.pw-sidenav__item--brand > .pw-icon { color: var(--pw-fg-brand); }
/* The count, the flame, the caret: whatever the row has to say after its name. */
.pw-sidenav__end { margin-inline-start: auto; display: inline-flex; align-items: center; gap: var(--pw-space-3); color: var(--pw-fg-tertiary); font-size: var(--pw-text-sm-size); }
/* A row that opens into others says so with a caret NEXT TO ITS NAME, small
   and quiet. Put at the far end it becomes a second control competing with the
   row's own menu for the same corner, and sized like one it reads as a button
   rather than as punctuation -- which is all it is. */
.pw-sidenav__caret { flex: none; margin-inline-start: var(--pw-space-3); color: var(--pw-fg-quaternary); }

/* The row's own menu, which appears on hover and on focus. Focus matters more
   than hover here: it is the only way a keyboard reaches it at all. */
.pw-sidenav__item .pw-sidenav__more { opacity: 0; transition: opacity var(--pw-duration-fast) var(--pw-ease-out); }
.pw-sidenav__item:hover .pw-sidenav__more,
.pw-sidenav__item:focus-within .pw-sidenav__more,
.pw-sidenav__item.is-current .pw-sidenav__more { opacity: 1; }

.pw-sidenav__label {
  display: flex; align-items: center; gap: var(--pw-space-4);
  padding: var(--pw-space-5) var(--pw-space-5) var(--pw-space-3);
  font-size: var(--pw-text-sm-size);
  font-weight: var(--pw-font-weight-semibold);
  color: var(--pw-fg-primary);
}
.pw-sidenav__label--quiet { font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-tertiary); text-transform: none; }
.pw-sidenav__label .pw-btn { margin-inline-start: auto; }
/* Nested chats under a project. Indented to the parent's text rather than to
   its icon, so the tree reads down the words. */
.pw-sidenav__sub { display: flex; flex-direction: column; gap: var(--pw-space-2); padding-inline-start: var(--pw-space-10); }
/* A scrolling list CLIPS, and a row is bigger than its box: the open chat is a
   raised card with a shadow under it, and any row can take a 4px focus ring.
   The inline axis had slack for that and the block axis had none, so the last
   chat in the list sat flush against the bottom edge and lost its ring and the
   underside of its card to it. The padding is the ring's own spread and the
   negative margin gives it back, so the list occupies exactly what it did
   before and every row has room to be pointed at. */
.pw-sidenav__scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  margin: calc(var(--pw-space-2) * -1);
  padding: var(--pw-space-2);
}
/* -- Sidebar projects -----------------------------------------------------------
   Each project with its icon; a row opens into its chats, indented to the
   project's name. A row's actions -- a new chat in it, its menu -- show on
   hover, on focus, and while it is open, the way a chat row's menu does. */
.pw-sideprojects { margin-block-end: var(--pw-space-4); }
.pw-sideprojects__head { gap: var(--pw-space-1); }
.pw-sideprojects__toggle {
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  margin-inline-end: auto; padding: 0; border: 0; background: none;
  color: inherit; font: inherit; cursor: pointer;
}
.pw-sideprojects__toggle .pw-icon { transition: transform var(--pw-duration-fast) var(--pw-ease-out); }
.pw-sideprojects__toggle[aria-expanded="false"] .pw-icon { transform: rotate(-90deg); }
.pw-sideprojects__head .pw-btn { margin-inline-start: 0; opacity: 0; transition: opacity var(--pw-duration-fast) var(--pw-ease-out); }
.pw-sideprojects__head:is(:hover, :focus-within) .pw-btn,
.pw-sideprojects__head .pw-btn[aria-expanded="true"] { opacity: 1; }
.pw-sideprojects__menu { position: relative; }
.pw-sideprojects__list { display: flex; flex-direction: column; gap: var(--pw-space-1); overflow: hidden; }
/* The same end padding as a chat row, so the project's ⋯ sits in the column
   its chats' ⋯ do. */
.pw-sideprojects__row { gap: var(--pw-space-1); padding-block: 0; }
.pw-sideprojects__open {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: center; gap: var(--pw-space-4);
  padding: var(--pw-space-3) 0; border: 0; background: none;
  color: inherit; font: inherit; text-align: start; cursor: pointer;
}
.pw-sideprojects__open > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-sideprojects__act { flex: none; position: relative; opacity: 0; transition: opacity var(--pw-duration-fast) var(--pw-ease-out); }
.pw-sideprojects__row:is(:hover, :focus-within) .pw-sideprojects__act,
.pw-sideprojects__project.is-open > .pw-sideprojects__row .pw-sideprojects__act,
.pw-sideprojects__act:has([aria-expanded="true"]) { opacity: 1; }
/* Hover and open share the soft fill; the project holding the current chat
   has its name at full strength; a project that is itself current (in one
   list) is the raised card every current row is. */
.pw-sideprojects__row:hover,
.pw-sideprojects__project.is-open > .pw-sideprojects__row:not(.is-current) { background: var(--pw-ink-hover); color: var(--pw-fg-primary); }
.pw-sideprojects__project.is-active > .pw-sideprojects__row { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-sideprojects__row:active:not(:has(.pw-btn:active)) { background: var(--pw-ink-pressed, var(--pw-ink-hover)); }
.pw-sideprojects__chats > .pw-sidenav__item:active { background: var(--pw-ink-pressed, var(--pw-ink-hover)); }
.pw-sideprojects__chats { overflow: hidden; padding-block: var(--pw-space-1); }
.pw-sideprojects__chats > .pw-sidenav__item > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-sideprojects__more { color: var(--pw-fg-tertiary); }
.pw-sideprojects__list > .pw-sideprojects__more { padding-inline-start: var(--pw-space-5); }
/* In one list: a project is a place to go, not a folder to open. */
[data-pw-organize="list"] .pw-sideprojects__chats { display: none; }
/* The project's symbol on its own, no tile: a sidebar row is already the
   tile. A light colour draws the symbol in grey so it still reads. */
.pw-project-icon.pw-project-icon--bare { --pw-project-size: 18px; background: none; box-shadow: none; border-radius: 0; }
.pw-project-icon.pw-project-icon--bare.is-light { background: none; color: var(--pw-fg-tertiary); box-shadow: none; }
.pw-project-icon.pw-project-icon--bare:hover { transform: none; }
/* A radio item in a menu: the check says which, not a fill. */
.pw-menu__item[role="menuitemradio"] .pw-menu__check { margin-inline-start: auto; visibility: hidden; }
.pw-menu__item[role="menuitemradio"][aria-checked="true"] { background: transparent; }
.pw-menu__item[role="menuitemradio"][aria-checked="true"]:hover { background: var(--pw-bg-hover); }
.pw-menu__item[role="menuitemradio"][aria-checked="true"] .pw-menu__check { visibility: visible; }

.pw-sidenav__rule { height: 1px; margin: var(--pw-space-5) var(--pw-space-5); background: var(--pw-border-faint); }
.pw-sidenav__foot { flex: 0 0 auto; padding-block-start: var(--pw-space-4); }
/* Privacy and Settings share a line because they are the same kind of thing --
   what this product does with you, and what you can tell it to do. */
.pw-sidenav__pair { display: flex; align-items: center; gap: var(--pw-space-3); }
.pw-sidenav__pair .pw-sidenav__item { width: auto; }
.pw-sidenav__pair .pw-sidenav__item:first-child > .pw-icon { color: var(--pw-color-success-500); }

/* THE SHELL HAS THREE SHAPES, and which one it wears is a question about the
   SHELL, not the window: a panel beside a thread is 272 of 1200 on a laptop and
   272 of 420 in a card on a documentation page, and the thread's own measure is
   what changes. */

/* 2. THE RAIL. A conversation is still readable next to 64px of icons, and a
      drawer costs a tap every time someone wants the thing they were just
      reading -- so the sidebar loses its words before it loses its place. */
@container (min-width: 561px) and (max-width: 820px) {
  .pw-appshell__aside { width: var(--pw-aside-rail); }
  .pw-appshell .pw-sidenav__item span,
  .pw-appshell .pw-sidenav__end,
  .pw-appshell .pw-sidenav__label,
  .pw-appshell .pw-sidenav__scroll { display: none; }
  .pw-appshell .pw-sidenav__logo { display: none !important; }
  .pw-appshell .pw-sidenav__head { justify-content: center; }
  .pw-appshell .pw-sidenav__head .pw-btn { margin-inline: auto; }
  .pw-appshell .pw-sidenav__item { justify-content: center; padding-inline: 0; }
  .pw-appshell .pw-sidenav__pair { flex-direction: column; }
  .pw-appshell .pw-sidenav__pair .pw-sidenav__item { width: 100%; }
}

/* 3. THE DRAWER. Below this there is no room to take 64px off the thread AND
      still read it, and a rail of six identical glyphs is not history anyway.
      So the sidebar leaves the layout and comes back whole -- titles, dates,
      the lot -- over the conversation, which is the only way the thing a
      sidebar is FOR survives a phone. It is the full panel, not a small one:
      a drawer that shows less than the sidebar did is a drawer nobody opens
      twice. */
@container (max-width: 560px) {
  .pw-appshell { grid-template-columns: minmax(0, 1fr); }
  .pw-appshell__aside {
    position: absolute; inset-block: 0; inset-inline-start: 0;
    /* ABOVE THE FLOATING BAR, which is also sticky-level and comes later in the
       DOM: left level with it the bar won on order alone and printed the
       personalisation switch across the drawer's own lockup. */
    z-index: calc(var(--pw-z-sticky) + 2);
    width: var(--pw-aside-wide);
    max-width: 86%;
    transform: translateX(-100%);
    box-shadow: var(--pw-shadow-xl);
    transition: transform var(--pw-duration-slow) var(--pw-ease-out);
  }
  .pw-appshell.is-drawer-open .pw-appshell__aside { transform: none; }
  /* The scrim is the shell's own pseudo-element rather than a div the
     controller injects: it is not content, nothing else needs to address it,
     and a layer that exists only while a class is on cannot be left behind. */
  .pw-appshell::before {
    content: ""; position: absolute; inset: 0;
    z-index: calc(var(--pw-z-sticky) + 1);
    background: var(--pw-bg-overlay);
    opacity: 0; pointer-events: none;
    transition: opacity var(--pw-duration-slow) var(--pw-ease-out);
  }
  .pw-appshell.is-drawer-open::before { opacity: 1; pointer-events: auto; }
  /* The way in. Hidden at every other size, because at every other size the
     sidebar is already on screen. */
  .pw-appshell__menu { display: inline-flex; }
}

/* Voice takes over the whole main column, bar included: while talking there is
   nothing in it to reach for. */
.pw-appshell__main > .pw-voice { z-index: calc(var(--pw-z-sticky) + 1); }

/* -- The home state ----------------------------------------------------------
   A new chat in the shell is the Start screen (.pw-start), centred in the body
   so the greeting and composer sit mid-page until the first message. */
.pw-appshell__body > .pw-start { min-height: 100%; justify-content: center; }

/* =============================================================================
   PROJECTS  —  a workspace with files and standing instructions
   A project is the answer to "I keep telling it the same three things". Its two
   cards are the two halves of that: what it can read, and what it must always
   do. Side by side because they are peers, and on the page rather than behind a
   settings icon because context you cannot see is context you cannot trust.
   ============================================================================= */
.pw-project { max-width: 768px; margin-inline: auto; }
.pw-project__title {
  margin-block-end: var(--pw-space-8);
  font-size: var(--pw-text-xl-size);
  line-height: var(--pw-text-xl-line);
  font-weight: var(--pw-font-weight-bold);
  color: var(--pw-fg-primary);
  text-align: center;
}
/* The project's name with its icon beside it, centred as one. */
.pw-project__head { display: flex; align-items: center; justify-content: center; gap: var(--pw-space-5); margin-block-end: var(--pw-space-8); }
.pw-project__head .pw-project__title { margin: 0; }

/* -- Project icon: a symbol and its colour --------------------------------------
   The tile tints itself with the colour and draws the symbol in it; a light
   colour (white, a tint) fills the tile instead and the symbol goes dark, so
   either reads. As a button it opens the picker; hover lifts it a little. */
.pw-project-icon {
  --pw-project-color: var(--pw-action-bg);
  --pw-project-size: 36px;
  flex: none; display: grid; place-items: center;
  width: var(--pw-project-size); height: var(--pw-project-size); padding: 0;
  border: 0; border-radius: var(--pw-radius-lg);
  background: color-mix(in srgb, var(--pw-project-color) 16%, var(--pw-bg-surface));
  color: var(--pw-project-color);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pw-project-color) 22%, transparent);
  cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), color var(--pw-duration-fast) var(--pw-ease-out), transform var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-project-icon.is-light { background: var(--pw-project-color); color: var(--pw-fg-secondary); box-shadow: inset 0 0 0 1px var(--pw-border-subtle); }
.pw-project-icon:hover { transform: scale(1.06); }
.pw-project-icon[aria-expanded="true"] { box-shadow: 0 0 0 2px var(--pw-bg-surface), 0 0 0 4px var(--pw-project-color); }
.pw-project-icon.is-light[aria-expanded="true"] { box-shadow: 0 0 0 2px var(--pw-bg-surface), 0 0 0 4px var(--pw-border-strong, var(--pw-fg-quaternary)); }
.pw-project-icon--sm { --pw-project-size: 24px; border-radius: var(--pw-radius-md); }
.pw-project-icon--sm .pw-icon { width: 14px; height: 14px; }
.pw-project-icon--lg { --pw-project-size: 44px; }
span.pw-project-icon { cursor: default; }
span.pw-project-icon:hover { transform: none; }

/* The picker: the colour wheel over the symbols. */
.pw-iconpick { width: 296px; padding: var(--pw-space-6); }
.pw-iconpick__label { margin: 0 0 var(--pw-space-4); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary); }
.pw-iconpick__palette { display: grid; place-items: center; margin-block-end: var(--pw-space-6); }
.pw-iconpick__grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: var(--pw-space-2); }
.pw-iconpick__icon {
  display: grid; place-items: center; aspect-ratio: 1; padding: 0;
  border: 0; border-radius: var(--pw-radius-md); background: transparent;
  color: var(--pw-fg-tertiary); cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-iconpick__icon:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-iconpick__icon[aria-checked="true"] { background: color-mix(in srgb, var(--pw-project-color) 16%, var(--pw-bg-surface)); color: var(--pw-project-color); }
.pw-iconpick.is-light .pw-iconpick__icon[aria-checked="true"] { background: var(--pw-bg-selected); color: var(--pw-fg-primary); }
.pw-iconpick__icon:focus-visible { outline: 2px solid var(--pw-focus-ring-color); outline-offset: 1px; }

/* A list of projects, as the sidebar shows them: the icon, then the name. */
.pw-projlist { display: flex; flex-direction: column; gap: var(--pw-space-1); width: 100%; max-width: 280px; }
.pw-projlist__head { display: flex; align-items: center; justify-content: space-between; padding: 0 0 var(--pw-space-3) var(--pw-space-4); font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary); }
.pw-projlist__item {
  display: flex; align-items: center; gap: var(--pw-space-4);
  padding: var(--pw-space-3) var(--pw-space-4); border-radius: var(--pw-radius-md);
  color: var(--pw-fg-secondary); font-size: var(--pw-text-sm-size); text-decoration: none;
}
.pw-projlist__item:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-projlist__item > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The name field with the icon at its start, for creating one. */
.pw-project-namefield { display: flex; align-items: center; gap: var(--pw-space-4); }
.pw-project-namefield .pw-input-wrap { flex: 1; min-width: 0; }
/* -- The composer's tray ------------------------------------------------------
   What the prompt will be answered WITH, tucked under the prompt itself: a
   project's files and its instructions. They used to be a separate two-card
   panel below the composer, which read as a second form -- and they are not a
   second thing to fill in, they are the context the first one runs in.

   The tray slides UNDER the composer's rounded bottom (a negative margin the
   size of that radius, given back as padding), so the two read as one object.
   The composer is lifted with `position: relative` and NO z-index: a z-index
   would make it a stacking context and trap its own menus inside it. Being
   positioned is enough to paint it above a non-positioned sibling.

   The fill is halfway between the composer's surface and the page's subtle
   fill, so it sits BETWEEN the two in either theme -- recessed under the
   composer, lifted off the page. (Mixing towards the text colour instead read
   recessed in light and raised in dark, where the text is the light end.) */
.pw-composer-dock--tray > .pw-composer { position: relative; }
.pw-composer-tray {
  --pw-tray-tuck: var(--pw-radius-2xl);
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--pw-space-1);
  margin-block-start: calc(var(--pw-tray-tuck) * -1);
  padding: calc(var(--pw-tray-tuck) + var(--pw-space-2)) var(--pw-space-4) var(--pw-space-3);
  border: 1px solid var(--pw-field-border);
  border-top: 0;
  border-radius: 0 0 var(--pw-radius-2xl) var(--pw-radius-2xl);
  background: color-mix(in srgb, var(--pw-bg-surface) 50%, var(--pw-bg-subtle));
}
.pw-composer-tray__item {
  display: inline-flex; align-items: center; gap: var(--pw-space-3);
  min-width: 0; max-width: 100%;
  height: 28px;
  padding-inline: var(--pw-space-4);
  border: 0; border-radius: var(--pw-radius-md);
  background: transparent;
  font-size: var(--pw-text-sm-size);
  color: var(--pw-fg-secondary);
  cursor: pointer;
  transition: background-color var(--pw-duration-instant) var(--pw-ease-out), color var(--pw-duration-instant) var(--pw-ease-out);
}
.pw-composer-tray__item:hover { background: color-mix(in srgb, var(--pw-fg-primary) 6%, transparent); color: var(--pw-fg-primary); }
.pw-composer-tray__item:focus-visible { outline: 2px solid var(--pw-color-brand-600); outline-offset: 0; }
.pw-composer-tray__item > .pw-icon { flex: none; color: var(--pw-fg-tertiary); }
.pw-composer-tray__label { flex: none; font-weight: var(--pw-font-weight-medium); }
/* The value is the answer, quieter than the question and cut to one line --
   once instructions are saved it is their first words. */
.pw-composer-tray__value {
  min-width: 0; max-width: 28ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--pw-fg-tertiary);
}
.pw-composer-tray__sep { flex: none; width: 1px; height: 14px; margin-inline: var(--pw-space-2); background: var(--pw-border-default); }
/* Narrow: the values go and the labels stay -- "Files" and "Instructions" are
   still findable, and the values are one press away. */
@container (max-width: 420px) {
  .pw-composer-tray__value { display: none; }
}

/* A chat inside a project. Wider than a sidebar row because there is room for
   the first line of it, and the first line is how anyone finds the one they
   mean -- titles in this product are generated and they repeat.

   The row is a DIV holding two sibling buttons: `__open`, stretched over the
   whole row, and the menu button above it. It used to be a <button> with the
   menu nested inside as a <span role="button"> -- an interactive element
   inside another is one the browser will not let you reach or press on its
   own, so the menu could never open. */
.pw-chatrow {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--pw-space-2) var(--pw-space-6);
  width: 100%;
  padding: var(--pw-space-6) var(--pw-space-7);
  border-radius: var(--pw-radius-lg);
  text-align: start;
  transition: background-color var(--pw-duration-instant) var(--pw-ease-out);
}
.pw-chatrow:hover, .pw-chatrow:has(> .pw-chatrow__more [aria-expanded="true"]) { background: var(--pw-bg-hover-on-subtle); }
/* The row's own action. Its name is the title (aria-labelledby) and the
   snippet describes it, so a screen reader hears the same row a reader sees. */
.pw-chatrow__open {
  position: absolute; inset: 0;
  border: 0; border-radius: inherit;
  background: transparent;
  cursor: pointer;
}
.pw-chatrow__open:focus-visible { outline: 2px solid var(--pw-color-brand-600); outline-offset: -2px; }
.pw-chatrow__title, .pw-chatrow__date, .pw-chatrow__snippet { pointer-events: none; }
.pw-chatrow__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-chatrow__date { font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); white-space: nowrap; }
.pw-chatrow__snippet {
  grid-column: 1 / -1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--pw-text-sm-size);
  color: var(--pw-fg-tertiary);
}
/* The menu takes the date's place on hover rather than sitting beside it. Two
   things in the same corner, one at a time: the date is what the row says at
   rest, the menu is what it offers when you are pointing at it.

   Both are ALWAYS laid out, stacked in one grid cell, and only their opacity
   changes: swapping them with `display` grew the row by the button's extra
   12px and made it appear in one frame. The button's negative block margins
   give that height back. It stays up while its menu is open, or the menu
   would fade out with it the moment the pointer moved into the menu. */
.pw-chatrow__date,
.pw-chatrow__more { grid-area: 1 / 2; justify-self: end; align-self: center; }
.pw-chatrow__date { transition: opacity var(--pw-duration-fast) var(--pw-ease-out); }
.pw-chatrow__more {
  position: relative; z-index: 1;
  display: flex;
  margin-block: -6px;
  opacity: 0; visibility: hidden;
  transition: opacity var(--pw-duration-fast) var(--pw-ease-out), visibility 0s linear var(--pw-duration-fast);
}
.pw-chatrow:is(:hover, :focus-within, :has(> .pw-chatrow__more [aria-expanded="true"])) .pw-chatrow__date { opacity: 0; }
.pw-chatrow:is(:hover, :focus-within, :has(> .pw-chatrow__more [aria-expanded="true"])) .pw-chatrow__more {
  opacity: 1; visibility: visible;
  transition: opacity var(--pw-duration-fast) var(--pw-ease-out), visibility 0s;
}
/* A project with no chats left says so, rather than showing an empty gap. */
.pw-chatlist:not(:has(.pw-chatrow)) > [data-pw-chatlist-empty] { display: block; }
[data-pw-chatlist-empty] { display: none; }

/* -- Files in a project ------------------------------------------------------
   The row states the file and its progress in the same line, because a
   progress bar that is not attached to a name is a progress bar for the dialog
   rather than for the file. Uploading and uploaded differ by one control: the
   spinner becomes a way to take it back out. */
.pw-filerow {
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-5) var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
.pw-filerow.is-busy { background: var(--pw-bg-subtle); }
/* Refused, not failed: the file never left the device. It stays in the list
   long enough to say why, and goes when dismissed. */
.pw-filerow.is-error { border-color: var(--pw-border-danger); }
.pw-filerow.is-error .pw-filerow__note { color: var(--pw-fg-danger); }
.pw-filerow__mark {
  display: grid; place-items: center;
  width: 32px; height: 32px; flex: none;
  border-radius: var(--pw-radius-sm);
  background: var(--pw-tint-danger-bg);
  color: var(--pw-tint-danger-fg);
  font-size: 9px; font-weight: var(--pw-font-weight-bold);
}
/* The mark's tint says what KIND of document it is before the name is read. */
.pw-filerow__mark--doc   { background: var(--pw-tint-brand-bg);   color: var(--pw-tint-brand-fg); }
.pw-filerow__mark--sheet { background: var(--pw-tint-success-bg); color: var(--pw-tint-success-fg); }
.pw-filerow__mark--deck  { background: var(--pw-tint-warning-bg); color: var(--pw-tint-warning-fg); }
.pw-filerow__mark--other { background: var(--pw-bg-muted);        color: var(--pw-fg-secondary); }
.pw-filerow__body { flex: 1 1 auto; min-width: 0; }
/* Five files, then the list scrolls on its own. The dropzone above it and the
   dialog's Done below it stay put: adding a tenth file should not push the
   place you add files from off the top. The cap is counted in ROWS, from the
   row's fixed height and the gap, so it stays exactly five whatever the
   height of the screen -- `--pw-filelist-rows` changes the count. */
.pw-filelist {
  --pw-filelist-rows: 5;
  --pw-filerow-h: 60px;
  display: flex; flex-direction: column; gap: var(--pw-space-4);
  max-height: calc(var(--pw-filelist-rows) * var(--pw-filerow-h) + (var(--pw-filelist-rows) - 1) * var(--pw-space-4));
  overflow-y: auto; overscroll-behavior: contain;
}
.pw-filelist > .pw-filerow { flex: none; min-height: var(--pw-filerow-h); box-sizing: border-box; }
.pw-filelist:empty { display: none; }
.pw-filerow__name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-filerow__note { display: block; font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line); color: var(--pw-fg-tertiary); }
/* The drop target. A dashed edge is the one place in this system where a border
   is not a hairline: it is saying "this rectangle is not a thing, it is a place
   to put a thing", and a solid edge says the opposite. */
.pw-dropzone {
  display: flex; flex-direction: column; align-items: center; gap: var(--pw-space-4);
  padding: var(--pw-space-10) var(--pw-space-8);
  border: 1px dashed var(--pw-border-default);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  text-align: center;
}
/* The whole rectangle takes a press, not only the link in it: it is the
   target people aim at. The link is there for the keyboard. */
.pw-dropzone[data-pw-dropzone] { cursor: pointer; transition: border-color var(--pw-duration-fast) var(--pw-ease-out), background-color var(--pw-duration-fast) var(--pw-ease-out); }
.pw-dropzone__text { font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); }
.pw-dropzone.is-over { border-color: var(--pw-color-brand-400); background: var(--pw-bg-selected); }
.pw-dropzone__mark {
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
  color: var(--pw-fg-tertiary);
  box-shadow: var(--pw-shadow-xs);
}
.pw-dropzone__hint { font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }

/* =============================================================================
   PERSONALISATION  —  standing instructions, and the tasks that use them
   ============================================================================= */
/* A saved prompt with a prefix. The prefix is the whole point of the row, so it
   is set in the mono face: it is something you TYPE, and type you have to type
   exactly is type that should not look like prose. */
.pw-task {
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-6) var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-bg-surface);
}
/* BLOCKS, so the prompt can be cut. `text-overflow` has nothing to work on
   inside an inline box: the line simply runs on, and it ran on under the edit
   and delete buttons -- the ellipsis appeared, because the flex item was
   clipped, but the last words were behind two icons. The row's text column has
   to end where the controls begin, and only a block box ends anywhere. */
.pw-task__body { flex: 1 1 auto; min-width: 0; display: block; }
.pw-task__name { display: block; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-task__prefix {
  margin-inline-start: var(--pw-space-4);
  padding: 1px var(--pw-space-4);
  border-radius: var(--pw-radius-sm);
  background: var(--pw-bg-muted);
  color: var(--pw-fg-secondary);
  font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--pw-text-xs-size);
}
.pw-task__prompt {
  display: block;
  margin-block-start: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--pw-text-xs-size);
  color: var(--pw-fg-tertiary);
}
/* The form that makes one, sunk into the card it will join. Sunk rather than
   floated, because it is not a dialog: nothing else is blocked while it is
   open, and the list it is about is still visible above it. */
.pw-task-form {
  display: flex; flex-direction: column; gap: var(--pw-space-7);
  padding: var(--pw-space-8);
  border-radius: var(--pw-radius-lg);
  background: var(--pw-skeleton-base);
}
.pw-task-form__foot { display: flex; align-items: center; justify-content: flex-end; gap: var(--pw-space-5); }
.pw-task-form__foot .pw-btn:first-child { margin-inline-end: auto; }

/* -----------------------------------------------------------------------------
   THE TOOLS' OWN PICKERS
   A tool chip is a control, so it opens something. What it opens differs by the
   question it is asking, and the shape of each picker is that question:
   a ratio is a PROPORTION, so it is shown as one; a style is a LOOK, so it is
   shown as one. A dropdown of words would make both of them a list of strings.
   ----------------------------------------------------------------------------- */
/* The proportion, drawn. Every box is inscribed in the same 26px square, so the
   shapes can be compared against each other rather than each being read off its
   own numbers -- which is the entire reason to draw them at all. */
.pw-ratio-box {
  flex: none;
  display: block;
  width: 26px; height: 26px;
  display: grid; place-items: center;
}
.pw-ratio-box::after {
  content: "";
  display: block;
  max-width: 26px; max-height: 26px;
  width: calc(26px * var(--pw-ratio-w, 1) / max(var(--pw-ratio-w, 1), var(--pw-ratio-h, 1)));
  height: calc(26px * var(--pw-ratio-h, 1) / max(var(--pw-ratio-w, 1), var(--pw-ratio-h, 1)));
  border: 1.5px solid var(--pw-border-strong);
  border-radius: var(--pw-radius-xs);
}
/* CHOSEN IS NEUTRAL here too, for the reason the chip is: these pickers say
   what a tool is set to, and the tool says it is on with a neutral fill. One
   brand-blue row inside them would make the answer a different kind of thing
   from the question. */
[aria-selected="true"] > .pw-ratio-box::after,
.is-selected > .pw-ratio-box::after { border-color: var(--pw-fg-primary); }
/* The row reads RATIO first, pixels second: the ratio is the question the
   control asks and the size is only how big that shape is rendered. Written the
   other way round -- which is how these menus usually come -- choosing "wide"
   means dividing 1344 by 768 in your head. */
/* The menu asks two questions and answers them side by side: WHAT SHAPE in two
   columns -- tall on the left, wide on the right, each row one proportion in
   both orientations -- and HOW BIG in a third, ruled off from them because it
   is a different question, not a third kind of shape. The square answers to
   neither column, so it spans them both. */
.pw-ratio-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--pw-space-4);
}
.pw-ratio-grid__ratios {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--pw-space-5);
  align-content: start;
}
.pw-ratio-grid__wide { grid-column: 1 / -1; }
/* The square spans both columns as a TARGET -- it is one choice, not two -- but
   its drawing still belongs in the left column's rail, or the one box that has
   no pair is also the one box that is somewhere else. Half the row, plus half
   the gutter, plus the padding the rows below carry -- that lands the drawing
   exactly where theirs land. */
.pw-ratio-grid__ratios .pw-select__option.pw-ratio-grid__wide {
  padding-inline-end: calc(50% + var(--pw-space-5) / 2 + var(--pw-space-5));
}
/* A rule, not a gap: the quality column is a separate question and the line is
   what says so. Its width is held so the pixel line under "4K" never wraps. */
.pw-ratio-grid__quality {
  min-width: 124px;
  padding-inline-start: var(--pw-space-4);
  border-inline-start: 1px solid var(--pw-border-subtle);
}
/* A floor under a short window: four rows always fit, but a 500px-tall laptop
   with the composer at the bottom does not owe anyone the whole menu. Scoped to
   THIS menu, never to .pw-menu, because a menu that scrolls is a scroll
   container, and a scroll container clips the submenu that opens beside it --
   which is exactly what Tools does with Tone. */
/* Three columns want 400px, and a phone does not have 400px to give: the width
   is a CEILING, not a measurement, and the same 12px the anchor keeps the panel
   off the viewport edge with. Fixed at 400 the quality column simply left the
   screen. */
.pw-ratio-menu { width: min(400px, calc(100vw - var(--pw-space-12))); }
.pw-ratio-menu { max-height: min(62vh, 420px); overflow-y: auto; overscroll-behavior: contain; }
.pw-ratio-menu .pw-select__option { justify-content: space-between; gap: var(--pw-space-4); font-variant-numeric: tabular-nums; }
.pw-ratio-grid__ratios .pw-select__option-title { flex: 1; min-width: 0; }
.pw-ratio-menu .pw-select__option[aria-selected="true"] { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-semibold); }
.pw-ratio-menu .pw-select__option[aria-selected="true"] .pw-select__option-desc { color: var(--pw-fg-secondary); font-weight: var(--pw-font-weight-regular); }

/* The look, shown. Two columns because a style is chosen by eye and the eye
   compares in pairs; a single column would make it a list to read down. */
.pw-style-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--pw-space-3);
  padding: var(--pw-space-3);
}
.pw-style {
  display: flex; align-items: center; gap: var(--pw-space-5);
  padding: var(--pw-space-3);
  border: 1.5px solid transparent;
  border-radius: var(--pw-radius-lg);
  background: transparent;
  color: var(--pw-fg-primary);
  font-size: var(--pw-text-sm-size);
  font-weight: var(--pw-font-weight-semibold);
  text-align: start;
  cursor: pointer;
}
.pw-style:hover { background: var(--pw-bg-hover); }
/* Outlined rather than filled: the swatch is the subject, and a fill behind it
   would be a second colour arguing with the one being chosen. */
.pw-style[aria-pressed="true"] { border-color: var(--pw-fg-primary); color: var(--pw-fg-primary); }
.pw-style__swatch {
  flex: none;
  width: 44px; height: 44px;
  border-radius: var(--pw-radius-md);
  background-size: cover; background-position: center;
}
/* The chosen style rides on its own chip, so the bar says which look is on
   without being opened. */
.pw-chip__thumb {
  flex: none;
  width: 18px; height: 18px;
  margin-inline-start: -2px;
  border-radius: var(--pw-radius-xs);
  background-size: cover; background-position: center;
}

/* =============================================================================
   TONE PAD  -- a tone is a place, not a word
   =============================================================================
   Two questions, asked at once: how formal (Professional .. Casual, the vertical
   axis) and how long (Concise .. Expanded, the horizontal one). A list of four
   tones could only ever answer one of them, and every tone between two words
   had no row. On a field the answer is a position, the four old tones are the
   four edges, and the presets are the corners.

   The handle's position is two custom properties, --pw-tone-x and --pw-tone-y,
   each -1..1. -1/1 lands on the centre of an outer cell, not on the edge of the
   field, so the handle is never half outside the thing it is in. GSAP writes
   the numbers (via a state object); CSS turns them into a place. Colour and
   the handle's scale are CSS transitions, and GSAP never touches either. */
/* 240px: the field is 214px square, which still gives each cell a 70px target
   and leaves the handle room to travel. */
.pw-tone-menu.pw-menu { width: min(240px, calc(100vw - var(--pw-space-12))); padding: 0; }
.pw-tone-pad { display: flex; flex-direction: column; }
.pw-tone-pad__head {
  display: flex; align-items: center; gap: var(--pw-space-4);
  min-height: 40px;
  padding: var(--pw-space-1) var(--pw-space-2) var(--pw-space-1) var(--pw-space-6);
  border-bottom: 1px solid var(--pw-border-subtle);
}
.pw-tone-pad__title { flex: 1; min-width: 0; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-tone-pad__body { display: flex; flex-direction: column; gap: var(--pw-space-5); padding: var(--pw-space-6); }

.pw-tone-pad__field {
  --pw-tone-x: 0; --pw-tone-y: 0;
  position: relative;
  aspect-ratio: 1;
  border: 1px solid var(--pw-border-default);
  border-radius: var(--pw-radius-lg);
  overflow: hidden;
  /* The field is the control. Without this a touch drag scrolls the page
     instead of moving the handle. */
  touch-action: none;
  cursor: pointer;
  user-select: none; -webkit-user-select: none;
}
/* The grid is drawn by the gaps between nine cells, so the lines are exactly
   the border colour and never a half-pixel gradient that blurs on 1x screens. */
.pw-tone-pad__grid {
  position: absolute; inset: 0;
  display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); gap: 1px;
  background: var(--pw-border-subtle);
}
.pw-tone-pad__grid > span { background: var(--pw-bg-subtle); transition: background-color var(--pw-duration-fast) var(--pw-ease-out); }
.pw-tone-pad__grid > span:hover { background: var(--pw-bg-hover); }

/* The axes. Quiet at rest, lit on the side the handle leans towards, so the
   field reads its own answer back in words. */
.pw-tone-pad__axis {
  position: absolute;
  font-size: var(--pw-text-xs-size); line-height: var(--pw-text-xs-line);
  font-weight: var(--pw-font-weight-medium);
  color: var(--pw-fg-quaternary);
  white-space: nowrap; pointer-events: none;
  transition: color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-tone-pad__axis.is-lit { color: var(--pw-fg-primary); }
.pw-tone-pad__axis[data-pw-axis="top"]    { top: var(--pw-space-2); left: 50%; translate: -50% 0; }
.pw-tone-pad__axis[data-pw-axis="bottom"] { bottom: var(--pw-space-2); left: 50%; translate: -50% 0; }
.pw-tone-pad__axis[data-pw-axis="left"]   { left: var(--pw-space-2); top: 50%; writing-mode: vertical-rl; rotate: 180deg; translate: 0 -50%; }
.pw-tone-pad__axis[data-pw-axis="right"]  { right: var(--pw-space-2); top: 50%; writing-mode: vertical-rl; translate: 0 -50%; }

/* Reset lives where the handle goes home to, and exists only once the handle
   has left: an undo for a change nobody made is a button that does nothing. */
.pw-tone-pad__reset {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  display: grid; place-items: center;
  width: 28px; height: 28px;
  border: 0; border-radius: var(--pw-radius-circle);
  background: transparent; color: var(--pw-fg-tertiary);
  cursor: pointer;
  opacity: 0; pointer-events: none;
  transition: opacity var(--pw-duration-fast) var(--pw-ease-out), background-color var(--pw-duration-instant) var(--pw-ease-out), color var(--pw-duration-instant) var(--pw-ease-out);
}
.pw-tone-pad.is-moved .pw-tone-pad__reset { opacity: 1; pointer-events: auto; }
.pw-tone-pad__reset:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-tone-pad__reset:focus-visible { outline: 2px solid var(--pw-color-brand-600); outline-offset: 2px; }

.pw-tone-pad__handle {
  position: absolute;
  left: calc(50% + var(--pw-tone-x) * 100% / 3);
  top:  calc(50% - var(--pw-tone-y) * 100% / 3);
  translate: -50% -50%;
  width: 26px; height: 26px;
  border: 3px solid var(--pw-bg-surface);
  border-radius: var(--pw-radius-circle);
  background: var(--pw-action-bg);
  box-shadow: var(--pw-shadow-md);
  cursor: grab;
  transition: scale var(--pw-duration-fast) var(--pw-ease-out), box-shadow var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-tone-pad__handle:focus-visible { outline: none; box-shadow: var(--pw-shadow-md), var(--pw-focus-ring); }
.pw-tone-pad.is-dragging .pw-tone-pad__handle { scale: 1.12; cursor: grabbing; box-shadow: var(--pw-shadow-lg); }
.pw-tone-pad.is-dragging .pw-tone-pad__field { cursor: grabbing; }

.pw-tone-pad__hint { margin: 0; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); }
.pw-tone-pad__presets { display: grid; grid-template-columns: 1fr 1fr; gap: var(--pw-space-3); }
.pw-tone-pad__presets > .pw-btn { width: 100%; }
/* A preset is lit while the handle stands on it, and goes out the moment it is
   dragged off -- the button says where you are, not what you last pressed. */
.pw-tone-pad__presets > .pw-btn[aria-pressed="true"] {
  background: var(--pw-bg-selected-neutral);
  border-color: var(--pw-border-strong);
  color: var(--pw-fg-primary);
}

/* Where a chat can be moved to. A fieldset for the grouping and its name, with
   the browser's frame taken off; the project it is already in is listed and
   disabled, so the list reads as "all your projects" rather than "some". */
.pw-chat-move { display: flex; flex-direction: column; gap: var(--pw-space-4); min-width: 0; margin: 0; padding: 0; border: 0; }


/* =============================================================================
   REASONING  —  a model working before it answers
   One line says what it is doing now, shimmering, with the thing it is working
   on in the text's full weight; what it thinks arrives underneath, line by
   line, quiet. When it is done the line becomes "Thought for 9s" and the
   thinking folds away behind it -- there to open, not in the way.
   ============================================================================= */
.pw-reason { margin-block-end: var(--pw-space-5); max-width: 640px; }
.pw-reason__head {
  display: inline-flex; align-items: center; gap: var(--pw-space-2);
  max-width: 100%; min-height: 28px; padding: 0; border: 0; background: none;
  font: inherit; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary);
  text-align: start; cursor: pointer;
}
.pw-reason__head:hover { color: var(--pw-fg-primary); }
.pw-reason__head:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: 2px; border-radius: var(--pw-radius-xs); }
.pw-reason__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-reason__label b { font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
/* The thing being worked on stays solid while the rest of the line shimmers. */
.pw-reason__label.pw-shimmer-text.is-shimmering:not(.is-still) b { -webkit-text-fill-color: var(--pw-fg-primary); }
.pw-reason__head > .pw-icon { flex: none; transition: transform var(--pw-duration-fast) var(--pw-ease-out); }
.pw-reason__head[aria-expanded="false"] > .pw-icon { transform: rotate(-90deg); }
[dir="rtl"] .pw-reason__head[aria-expanded="false"] > .pw-icon { transform: rotate(90deg); }
.pw-reason[data-state="thinking"] .pw-reason__head > .pw-icon { display: none; }
.pw-reason__body {
  display: flex; flex-direction: column; gap: var(--pw-space-4);
  margin-block-start: var(--pw-space-3);
  padding-inline-start: var(--pw-space-6);
  border-inline-start: 1px solid var(--pw-border-subtle);
  font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-tertiary);
}
.pw-reason__body p { margin: 0; }

/* =============================================================================
   FILE DIFF  —  a change an agent proposes to a file
   The file, how much changes (+3 −1), and the lines: both numbers in the
   gutter, removed lines tinted and marked with a hatched edge, added ones
   tinted with a solid edge -- two marks that differ in shape as well as
   colour. Follows the theme like the code block, and shares its syntax
   colours. Unchanged runs between hunks fold to one row that says how many.
   ============================================================================= */
.pw-diff {
  margin-block: var(--pw-space-6);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-lg);
  background: var(--pw-code-bg); overflow: hidden;
}
.pw-diff__head {
  display: flex; align-items: center; gap: var(--pw-space-4);
  min-height: 40px; padding: var(--pw-space-2) var(--pw-space-3) var(--pw-space-2) var(--pw-space-6);
  border-block-end: 1px solid var(--pw-code-rule);
  font-size: var(--pw-text-xs-size); color: var(--pw-code-muted);
}
.pw-diff__head > .pw-icon { flex: none; }
.pw-diff__path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); color: var(--pw-code-fg); }
.pw-diff__stat { display: inline-flex; gap: var(--pw-space-2); margin-inline-end: auto; font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-variant-numeric: tabular-nums; }
.pw-diff__stat .is-add { color: var(--pw-fg-success); }
.pw-diff__stat .is-del { color: var(--pw-fg-danger); }
.pw-diff__tools { display: flex; align-items: center; gap: var(--pw-space-1); }
.pw-diff__head .pw-btn--ghost { color: var(--pw-code-muted); }
.pw-diff__head .pw-btn--ghost:hover { background: var(--pw-code-hover); color: var(--pw-code-fg); }
.pw-diff__head .pw-diff__toggle .pw-icon { transition: transform var(--pw-duration-fast) var(--pw-ease-out); }
.pw-diff.is-collapsed .pw-diff__toggle .pw-icon { transform: rotate(-90deg); }
.pw-diff.is-collapsed .pw-diff__head { border-block-end-color: transparent; }
.pw-diff__src { display: none; }
.pw-diff__body { overflow-x: auto; }
.pw-diff__table {
  width: 100%; border-collapse: collapse;
  font-family: var(--pw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--pw-text-xs-size); line-height: 22px; color: var(--pw-code-fg);
}
.pw-diff__table td { padding: 0; white-space: pre; vertical-align: top; }
.pw-diff__num {
  width: 1%; min-width: 3ch; padding-inline: var(--pw-space-3) !important;
  text-align: end; color: var(--pw-code-gutter); user-select: none; font-variant-numeric: tabular-nums;
}
.pw-diff__num + .pw-diff__num { padding-inline-end: var(--pw-space-4) !important; }
.pw-diff__sign { width: 1%; padding-inline: var(--pw-space-2) var(--pw-space-3) !important; color: var(--pw-code-gutter); user-select: none; }
.pw-diff__code { padding-inline-end: var(--pw-space-7) !important; }
.pw-diff__row--add { background: var(--pw-code-add); }
.pw-diff__row--del { background: var(--pw-code-del); }
.pw-diff__row--add .pw-diff__sign { color: var(--pw-fg-success); }
.pw-diff__row--del .pw-diff__sign { color: var(--pw-fg-danger); }
.pw-diff__row--add > td:first-child { box-shadow: inset 3px 0 0 var(--pw-fg-success); }
.pw-diff__row--del > td:first-child {
  background-image: repeating-linear-gradient(135deg, var(--pw-fg-danger) 0 1.5px, transparent 1.5px 4px);
  background-size: 3px 100%; background-repeat: no-repeat;
}
[dir="rtl"] .pw-diff__row--add > td:first-child { box-shadow: inset -3px 0 0 var(--pw-fg-success); }
[dir="rtl"] .pw-diff__row--del > td:first-child { background-position: right; }
.pw-diff__row--hunk td { padding-block: 2px !important; color: var(--pw-code-muted); background: var(--pw-code-hover); font-family: inherit; }
.pw-diff__table tr:first-child td { padding-block-start: var(--pw-space-3); }
.pw-diff__table tr:last-child td { padding-block-end: var(--pw-space-3); }
/* Decided: the proposal's buttons give way to what was decided. */
.pw-diff__decided { display: none; align-items: center; gap: var(--pw-space-2); font-weight: var(--pw-font-weight-semibold); }
.pw-diff[data-state="applied"] .pw-diff__decided, .pw-diff[data-state="rejected"] .pw-diff__decided { display: inline-flex; }
.pw-diff[data-state="applied"] .pw-diff__decided { color: var(--pw-fg-success); }
.pw-diff[data-state="rejected"] { opacity: .72; }
.pw-diff:is([data-state="applied"], [data-state="rejected"]) [data-pw-diff-act] { display: none; }

/* =============================================================================
   TASK LIST  —  the steps an agent is working through
   A card with a ring that fills as tasks finish and a count. The task in hand
   shimmers with how far along it is; done ones are ticked and quiet. Folded,
   the head says which task is running, so the list can close without the
   work disappearing.
   ============================================================================= */
.pw-tasklist {
  max-width: 520px; margin-block: var(--pw-space-5);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
}
.pw-tasklist__head {
  display: flex; align-items: center; gap: var(--pw-space-4);
  width: 100%; min-height: 44px; padding: var(--pw-space-3) var(--pw-space-6);
  border: 0; background: none; font: inherit; text-align: start; cursor: pointer;
  color: var(--pw-fg-primary); border-radius: inherit;
}
.pw-tasklist__head:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: -2px; }
.pw-tasklist__ring { flex: none; width: 16px; height: 16px; }
.pw-tasklist__ring circle { fill: none; stroke-width: 2; }
.pw-tasklist__ring .is-track { stroke: var(--pw-border-default); }
.pw-tasklist__ring .is-fill { stroke: var(--pw-action-bg); stroke-linecap: round; transform: rotate(-90deg); transform-origin: center; }
.pw-tasklist__title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); }
.pw-tasklist__now { display: none; font-weight: var(--pw-font-weight-regular); color: var(--pw-fg-secondary); }
.pw-tasklist.is-collapsed .pw-tasklist__now { display: inline; }
.pw-tasklist__count { flex: none; font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-tasklist__head > .pw-icon { flex: none; color: var(--pw-fg-tertiary); transition: transform var(--pw-duration-fast) var(--pw-ease-out); }
.pw-tasklist.is-collapsed .pw-tasklist__head > .pw-icon { transform: rotate(-90deg); }
.pw-tasklist__items { list-style: none; margin: 0; padding: 0 var(--pw-space-6) var(--pw-space-5); display: flex; flex-direction: column; gap: var(--pw-space-1); }
.pw-tasklist__item { display: flex; align-items: center; gap: var(--pw-space-4); min-height: 28px; font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); }
.pw-tasklist__mark {
  flex: none; display: grid; place-items: center;
  width: 16px; height: 16px; border-radius: var(--pw-radius-circle);
  border: 1.5px solid var(--pw-border-strong); color: var(--pw-bg-surface);
}
.pw-tasklist__mark .pw-icon { width: 10px; height: 10px; opacity: 0; }
.pw-tasklist__text { flex: 1 1 auto; min-width: 0; }
.pw-tasklist__pct { flex: none; padding: 0 var(--pw-space-2); border-radius: var(--pw-radius-xs); background: var(--pw-bg-muted); font-size: 11px; color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-tasklist__item:not([data-status="active"]) .pw-tasklist__pct { display: none; }
.pw-tasklist__item[data-status="active"] { color: var(--pw-fg-primary); }
/* In progress: a dashed ring that turns (the controller turns it with GSAP),
   so a running task reads as moving even when its percentage is not. */
.pw-tasklist__item[data-status="active"] .pw-tasklist__mark { border-style: dashed; border-color: var(--pw-action-bg); }
.pw-tasklist__item[data-status="done"] { color: var(--pw-fg-tertiary); }
.pw-tasklist__item[data-status="done"] .pw-tasklist__text { text-decoration: line-through; text-decoration-color: var(--pw-border-strong); }
.pw-tasklist__item[data-status="done"] .pw-tasklist__mark { border-color: var(--pw-action-bg); background: var(--pw-action-bg); color: var(--pw-action-fg); }
.pw-tasklist__item[data-status="done"] .pw-tasklist__mark .pw-icon { opacity: 1; }
.pw-tasklist__item[data-status="failed"] { color: var(--pw-fg-danger); }
.pw-tasklist__item[data-status="failed"] .pw-tasklist__mark { border-color: var(--pw-fg-danger); background: var(--pw-fg-danger); }
.pw-tasklist__item[data-status="failed"] .pw-tasklist__mark .pw-icon { opacity: 1; }

/* =============================================================================
   PLAN CARD  —  a plan an agent is asking to run
   What it will do, the to-dos (three shown, the rest one press away), and the
   decision: Approve, look at the whole plan first, or let it approve itself
   when the ring runs out. The countdown is a courtesy, not a trap: a press
   anywhere on it stops it.
   ============================================================================= */
.pw-plancard {
  max-width: 560px; margin-block: var(--pw-space-5); padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
}
.pw-plancard__head { display: flex; align-items: center; gap: var(--pw-space-5); }
.pw-plancard__icon { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--pw-radius-md); background: var(--pw-bg-muted); color: var(--pw-fg-secondary); }
.pw-plancard__title { flex: 1 1 auto; min-width: 0; margin: 0; font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-plancard__summary { margin: var(--pw-space-5) 0 0; font-size: var(--pw-text-sm-size); line-height: var(--pw-text-sm-line); color: var(--pw-fg-secondary); }
.pw-plancard__todos { margin-block-start: var(--pw-space-6); padding: var(--pw-space-5) var(--pw-space-6); border-radius: var(--pw-radius-lg); background: var(--pw-bg-subtle); }
.pw-plancard__todos-head { display: flex; align-items: center; gap: var(--pw-space-3); font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-plancard__todos-head span:last-child { margin-inline-start: auto; font-weight: var(--pw-font-weight-regular); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-plancard__list { list-style: none; margin: var(--pw-space-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--pw-space-3); }
.pw-plancard__list li { display: flex; align-items: center; gap: var(--pw-space-4); font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); }
.pw-plancard__list li::before { content: ""; flex: none; width: 12px; height: 12px; border-radius: var(--pw-radius-circle); border: 1.5px solid var(--pw-border-strong); }
.pw-plancard__more { display: inline-flex; align-items: center; gap: var(--pw-space-3); margin-block-start: var(--pw-space-3); padding: 0; border: 0; background: none; font: inherit; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); cursor: pointer; }
.pw-plancard__more:hover { color: var(--pw-fg-primary); }
.pw-plancard__foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--pw-space-4); margin-block-start: var(--pw-space-6); }
.pw-plancard__auto { display: inline-flex; align-items: center; gap: var(--pw-space-3); margin-inline-end: auto; padding: var(--pw-space-2) var(--pw-space-3) var(--pw-space-2) var(--pw-space-2); border: 0; border-radius: var(--pw-radius-pill); background: none; font: inherit; font-size: var(--pw-text-sm-size); color: var(--pw-fg-secondary); cursor: pointer; }
.pw-plancard__auto:hover { background: var(--pw-bg-hover); color: var(--pw-fg-primary); }
.pw-plancard__auto svg { width: 18px; height: 18px; flex: none; }
.pw-plancard__auto-label { white-space: nowrap; font-variant-numeric: tabular-nums; }
.pw-plancard__auto circle { fill: none; stroke-width: 2; }
.pw-plancard__auto .is-track { stroke: var(--pw-border-default); }
.pw-plancard__auto .is-fill { stroke: var(--pw-action-bg); stroke-linecap: round; transform: rotate(-90deg); transform-origin: center; }
.pw-plancard__auto.is-off .is-fill { stroke: transparent; }
.pw-plancard__approve .pw-kbd { margin-inline-start: var(--pw-space-2); border-color: color-mix(in srgb, currentColor 30%, transparent); background: color-mix(in srgb, currentColor 14%, transparent); color: inherit; }
.pw-plancard__status { display: none; align-items: center; gap: var(--pw-space-3); margin-inline-end: auto; font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-success); }
.pw-plancard[data-state="approved"] .pw-plancard__status { display: inline-flex; }
.pw-plancard[data-state="approved"] :is(.pw-plancard__auto, .pw-plancard__approve) { display: none; }

/* =============================================================================
   QUESTION CARD  —  what an agent needs answered before it goes on
   One question at a time: the question, why it matters, lettered answers the
   keyboard can pick (A, B, C...), and "Something else" to write one. A ring
   says how many are left. Skip is always there; Next waits for an answer.
   When the last is answered the card folds to what was said.
   ============================================================================= */
.pw-qcard {
  max-width: 560px; margin-block: var(--pw-space-5); padding: var(--pw-space-7);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-xl);
  background: var(--pw-bg-surface);
}
.pw-qcard__head { display: flex; align-items: center; gap: var(--pw-space-4); font-size: var(--pw-text-sm-size); font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-primary); }
.pw-qcard__icon { display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--pw-radius-md); background: var(--pw-bg-muted); color: var(--pw-fg-secondary); }
.pw-qcard__progress { display: inline-flex; align-items: center; gap: var(--pw-space-3); margin-inline-start: auto; font-weight: var(--pw-font-weight-regular); font-size: var(--pw-text-xs-size); color: var(--pw-fg-tertiary); font-variant-numeric: tabular-nums; }
.pw-qcard__progress svg { width: 18px; height: 18px; }
.pw-qcard__count { min-width: 44px; }
.pw-qcard__next-label { display: inline; }
.pw-qcard__progress circle { fill: none; stroke-width: 2; }
.pw-qcard__progress .is-track { stroke: var(--pw-border-default); }
.pw-qcard__progress .is-fill { stroke: var(--pw-action-bg); stroke-linecap: round; transform: rotate(-90deg); transform-origin: center; }
.pw-qcard__q[hidden] { display: none; }
.pw-qcard__question { margin: var(--pw-space-6) 0 0; font-size: var(--pw-text-md-size); line-height: var(--pw-text-md-line); font-weight: var(--pw-font-weight-medium); color: var(--pw-fg-primary); }
.pw-qcard__hint { margin: var(--pw-space-2) 0 0; font-size: var(--pw-text-sm-size); color: var(--pw-fg-tertiary); }
.pw-qcard__options { display: flex; flex-direction: column; gap: var(--pw-space-2); margin-block-start: var(--pw-space-5); }
.pw-qcard__opt {
  display: flex; align-items: center; gap: var(--pw-space-5);
  width: 100%; min-height: 40px; padding: var(--pw-space-2) var(--pw-space-4);
  border: 1px solid transparent; border-radius: var(--pw-radius-lg);
  background: none; font: inherit; font-size: var(--pw-text-sm-size); color: var(--pw-fg-primary);
  text-align: start; cursor: pointer;
  transition: background-color var(--pw-duration-fast) var(--pw-ease-out), border-color var(--pw-duration-fast) var(--pw-ease-out);
}
.pw-qcard__opt:hover { background: var(--pw-bg-hover); }
.pw-qcard__opt:focus-visible { outline: 2px solid var(--pw-border-brand); outline-offset: -2px; }
.pw-qcard__opt[aria-checked="true"] { border-color: transparent; background: var(--pw-bg-selected); }
.pw-qcard__key {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px;
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-sm);
  /* Its own line: inherited, the answer's 28px line pushed the letter below
     the middle of the 22px box. */
  font-size: 11px; line-height: 1; font-weight: var(--pw-font-weight-semibold); color: var(--pw-fg-tertiary);
}
.pw-qcard__opt[aria-checked="true"] .pw-qcard__key { border-color: var(--pw-action-bg); background: var(--pw-action-bg); color: var(--pw-action-fg); }
.pw-qcard__other { flex: 1 1 auto; min-width: 0; border: 0; padding: 0; background: none; font: inherit; color: var(--pw-fg-primary); outline: none; }
.pw-qcard__other::placeholder { color: var(--pw-fg-tertiary); }
.pw-qcard__foot { display: flex; justify-content: flex-end; gap: var(--pw-space-3); margin-block-start: var(--pw-space-6); }
.pw-qcard__next .pw-kbd { margin-inline-start: var(--pw-space-2); border-color: color-mix(in srgb, currentColor 30%, transparent); background: color-mix(in srgb, currentColor 14%, transparent); color: inherit; }
.pw-qcard__done { display: none; margin: var(--pw-space-5) 0 0; padding: 0; list-style: none; flex-direction: column; gap: var(--pw-space-4); }
.pw-qcard__done li { display: flex; flex-direction: column; gap: 2px; font-size: var(--pw-text-sm-size); }
.pw-qcard__done li span:first-child { color: var(--pw-fg-tertiary); }
.pw-qcard__done li span:last-child { color: var(--pw-fg-primary); font-weight: var(--pw-font-weight-medium); }
.pw-qcard[data-state="answered"] .pw-qcard__done { display: flex; }
.pw-qcard[data-state="answered"] :is(.pw-qcard__q, .pw-qcard__foot) { display: none; }

/* =============================================================================
   MESSAGE SCROLLER  —  a conversation that scrolls
   The thread fades at whichever edge has more; a round button brings the
   reader back to the newest message, and says so when something new arrived
   while they were reading back. While the reader is at the bottom, new words
   keep them there; once they scroll up, nothing pulls them down.
   ============================================================================= */
.pw-msgscroll { position: relative; display: flex; flex-direction: column; min-height: 0; }
.pw-msgscroll__view {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  --pw-fade-top: 0px; --pw-fade-bottom: 0px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, var(--pw-fg-primary) var(--pw-fade-top), var(--pw-fg-primary) calc(100% - var(--pw-fade-bottom)), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, var(--pw-fg-primary) var(--pw-fade-top), var(--pw-fg-primary) calc(100% - var(--pw-fade-bottom)), transparent 100%);
}
.pw-msgscroll__view.has-above { --pw-fade-top: 32px; }
.pw-msgscroll__view.has-below { --pw-fade-bottom: 48px; }
.pw-msgscroll__jump {
  position: absolute; inset-block-end: var(--pw-space-5); left: 50%; translate: -50% 0; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--pw-space-2);
  min-width: 32px; height: 32px; padding: 0 var(--pw-space-3);
  border: 1px solid var(--pw-border-subtle); border-radius: var(--pw-radius-pill);
  background: var(--pw-bg-surface); color: var(--pw-fg-primary); box-shadow: var(--pw-shadow-md);
  font: inherit; font-size: var(--pw-text-xs-size); font-weight: var(--pw-font-weight-semibold); cursor: pointer;
}
.pw-msgscroll__jump[hidden] { display: none; }
.pw-msgscroll__jump:hover { background: var(--pw-bg-hover); }
.pw-msgscroll__new { display: none; padding-inline-end: var(--pw-space-2); }
.pw-msgscroll__jump.has-new .pw-msgscroll__new { display: inline; }
.pw-msgscroll__jump.has-new { padding-inline-start: var(--pw-space-5); }
