/* =================================================================
   composer-controls.css — the usage ring and the effort slider
   -----------------------------------------------------------------
   Moved out of pages/code.css, verbatim and in their original order, so
   the home page composer can carry the same two controls as the builder
   instead of a second, lesser version of them. The builder had them and
   the home page did not: a build started there could not be set to Max,
   and ran at whatever the builder had last saved.

   Only the controls themselves live here. How a composer row squeezes
   them (.ag-brow ...) and where their popovers sit on a narrow screen
   stay with each page, because that is layout and the two pages differ.
   ================================================================= */
  /* ---- the usage ring ----
     Two circles and one custom property. The arc starts at the top because
     a gauge beginning at three o'clock reads as a slice of a pie rather
     than as a proportion. r=9, so the circumference is 56.55 and the dash
     offset is the unfilled remainder of it. */
  .ag-usage-btn{flex:none;width:30px;height:30px;border:1px solid var(--line);
    background:transparent;border-radius:999px;display:grid;place-items:center;
    cursor:pointer;padding:0;color:var(--accent);
    transition:border-color var(--dur-snappy,.12s) ease,background-color var(--dur-snappy,.12s) ease}
  .ag-usage-btn:hover{border-color:var(--ink-2);
    background:color-mix(in srgb,currentColor 10%,transparent)}
  .ag-usage-btn svg{width:18px;height:18px;transform:rotate(-90deg);overflow:visible}
  .ag-usage-btn circle{fill:none;stroke-width:3}
  .ag-usage-btn .trk{stroke:color-mix(in srgb,currentColor 22%,transparent)}
  .ag-usage-btn .arc{stroke:currentColor;stroke-linecap:round;
    stroke-dasharray:56.55;
    stroke-dashoffset:calc(56.55 - (56.55 * var(--pct,0) / 100));
    transition:stroke-dashoffset var(--dur-chill,.3s) var(--ease-snappy,ease-out)}
  .ag-usage-btn.warn{color:var(--warn)}
  .ag-usage-btn.hot{color:var(--danger)}
  @media (prefers-reduced-motion:reduce){
    .ag-usage-btn,.ag-usage-btn .arc{transition:none}
  }

  /* ---- the panel it opens ---- */
  .ag-usagepop{position:fixed;z-index:130;width:min(300px,calc(100vw - 16px));
    background:var(--card);border:1px solid var(--line);border-radius:14px;
    padding:12px 13px;box-shadow:0 16px 40px -10px rgba(11,22,38,.45);
    opacity:0;visibility:hidden;transform:translateY(4px);
    transition:opacity .16s ease,transform .16s ease,visibility .16s ease}
  /* .ag-chatpop carries one of these and it is not decoration: a 45%
     blue-black shadow under a #26282b card is invisible, so in dark mode
     the panel lost its edge and read as part of the composer it floats
     over. Same two-layer shape the chat popover uses. */
  :root[data-theme="dark"] .ag-usagepop{
    box-shadow:0 4px 10px -4px rgba(0,0,0,.5),0 24px 52px -20px rgba(0,0,0,.85)}
  .ag-usagepop.open{opacity:1;visibility:visible;transform:none}
  /* Under the context row, naming the real threshold. The number is
     AUTO_COMPACT_AT in agent-src/lib/codeagent/context/token-budget.ts; if
     that moves this line is wrong and says so confidently. */
  .u-note{margin:0;font-size:.68rem;color:var(--mut);line-height:1.45}

  .u-more{display:block;margin-top:10px;padding-top:9px;border-top:1px solid var(--line);
    font-size:.74rem;font-weight:600;color:var(--accent);text-decoration:none}
  .u-more:hover{text-decoration:underline}
  .u-more::after{content:" \2192"}
  @media (prefers-reduced-motion:reduce){ .ag-usagepop{transition:none} }

  /* ── EFFORT ───────────────────────────────────────────────────────────
     How hard to think, as one value on a range rather than a mode you had
     to know to pair with something else. Reads as a value, not a menu: no
     chevron, because it opens a slider and not a list. */
  .ag-effort-wrap{position:relative;display:inline-flex;flex:none}
  /* Bordered at rest, like the two controls beside it. Transparent until
     hover, it was the only thing on that row that did not look pressable
     until you had already found it - and the row reads as a set of three
     buttons, so one of them being a bare word broke the set. */
  .ag-effort-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:8px;
    border:1px solid var(--line);background:var(--card);cursor:pointer;
    font:inherit;font-size:.78rem;font-weight:600;color:var(--ink-2);
    transition:background .18s var(--ease),border-color .18s var(--ease),color .18s var(--ease)}
  /* THE PILL IS AS WIDE AS ITS WIDEST LABEL, ALWAYS.
     The level name changes as you drag, and the names are not the same
     length: "Fast" measured 47.1px and "Balanced" 77.5px, so the pill
     swung 30.4px and every control to its right - the model pill, the
     mic, the send button - slid by exactly that much. Dragging the
     slider made the whole composer row shuffle sideways under the
     cursor, and on a narrow composer it was enough to wrap the row.

     Every label is in the DOM, stacked in one grid cell; the three that
     are not current are visibility:hidden, so they still take part in
     sizing and nothing else. A min-width in px would do the same job
     until the font, the type scale or the wording changed; this cannot
     go stale, because the thing being measured IS the set of labels. */
  .ag-effort-lbl{display:grid;justify-items:center}
  .ag-effort-lbl>*{grid-area:1/1}
  .ag-effort-lbl>i{visibility:hidden;font-style:normal;pointer-events:none}
  .ag-effort-pill:hover{background:var(--paper-2);border-color:var(--line-hover)}
  .ag-effort-pill.open{background:var(--paper-2);border-color:var(--line-hover)}
  /* No indicator dot. The level's NAME is the indicator — a coloured bead
     beside a word that already says the same thing is one signal too many,
     and the reference carries none. The top of the scale still tints the
     label so it is readable at a glance. */
  .ag-effort-pill[data-level="smart"],
  .ag-effort-pill[data-level="max"]{color:var(--accent)}

  .ag-effort-tip{position:absolute;bottom:calc(100% + 7px);left:50%;transform:translateX(-50%) translateY(3px);
    background:var(--ink);color:var(--paper);font-size:.7rem;font-weight:600;
    padding:3px 8px;border-radius:6px;white-space:nowrap;pointer-events:none;
    opacity:0;transition:opacity .14s var(--ease),transform .14s var(--ease);z-index:60}
  .ag-effort-wrap:hover .ag-effort-tip{opacity:1;transform:translateX(-50%) translateY(0)}
  .ag-effort-wrap:has(.ag-effort-pop.open) .ag-effort-tip{opacity:0}

  /* Narrower and shorter than it was. The description line went with it:
     the level name IS the description once you have read it once, and a
     paragraph re-rendering under your thumb is noise while you drag. */
  .ag-effort-pop{position:absolute;bottom:calc(100% + 10px);right:0;width:252px;z-index:70;
    background:var(--card);border:1px solid var(--line);border-radius:15px;padding:13px 15px 14px;
    box-shadow:0 18px 44px -18px rgba(23,23,23,.28),0 2px 8px -5px rgba(23,23,23,.14);
    opacity:0;visibility:hidden;transform:translateY(5px) scale(.975);transform-origin:100% 100%;
    transition:opacity .2s cubic-bezier(.2,.8,.2,1),transform .24s cubic-bezier(.2,.8,.2,1),visibility .24s}
  .ag-effort-pop.open{opacity:1;visibility:visible;transform:none;
    /* Visible at once on the way in; the fade is opacity's job. A
       visibility that transitions stays `hidden` until the first frame has
       run, and open() focuses the slider before that — the focus was
       refused, so the keyboard could never reach the control. */
    transition:opacity .2s cubic-bezier(.2,.8,.2,1),transform .24s cubic-bezier(.2,.8,.2,1),visibility 0s}
  :root[data-theme="dark"] .ag-effort-pop{
    box-shadow:0 22px 48px -18px rgba(0,0,0,.72),0 2px 10px -5px rgba(0,0,0,.5)}

  .ag-effort-head{display:flex;align-items:center;gap:7px;margin-bottom:11px}
  .ag-effort-head .k{font-size:.78rem;font-weight:500;color:var(--mut)}
  .ag-effort-head .v{font-size:.78rem;font-weight:600;color:var(--accent);
    transition:opacity .16s var(--ease)}
  .ag-effort-head .v.swap{opacity:0}
  .ag-effort-head .q{margin-inline-start:auto;width:14px;height:14px;color:var(--mut);flex:none;opacity:.55}

  .ag-effort-ends{display:flex;justify-content:space-between;font-size:.7rem;color:var(--mut);margin-bottom:6px}

  .ag-effort-row{display:flex;align-items:center;gap:9px}
  .ag-effort-track{position:relative;flex:1 1 auto;height:26px;min-width:0}

  /* THE RAMP IS THE DOTS THEMSELVES.
     Three grids of the same 7px pitch, each a heavier dot than the last,
     faded in over a different stretch of the track. Stacked, the left end is
     a faint speckle and the right is solid — so the control says "more" by
     getting denser, which is the thing you can read without reading.

     There is no lit bar over the top. An overlay that filled to the thumb
     was the first attempt and it destroyed the ramp: at the top of the scale
     it painted full-strength dots across the whole width, so Max and Fast
     looked identical apart from where the handle sat. The gradient is
     static; only the thumb moves. */
  .ag-effort-track .dots,
  .ag-effort-track .dots::before,
  .ag-effort-track .dots::after{
    position:absolute;inset:0;border-radius:8px;content:"";pointer-events:none}
  /* THE GRAIN IS THE SCALE. THE BLUE IS MAX.

     The ramp is a dot grain that densifies toward "Smarter" — that is the
     scale itself, and it is there at every level, because it is what makes
     the positions mean something. What it is NOT is blue: a filled band at
     every level said "full power" four times over and left the top of the
     scale with nothing of its own to say.

     The fill belongs to Max alone, and it arrives rather than appearing —
     wiped in from the left over about a second and a half, with the bright
     head of the run travelling just ahead of it. That is the whole point of
     it: you see the track charge.

     On scale: the pitch was 7px with dots at 26/33/40% of the cell, 3.6 to
     5.6px across and about three and a half rows on a 26px track. At that
     size you do not read a density, you read a printed halftone. 4px pitch
     at ~17% is roughly 1.4px across and six and a half rows, fine enough to
     read as texture.

     Every grain layer sits on the SAME 4px lattice, aligned. Offsetting the
     heavier ones by half a cell was tried and is worse: it puts dots
     BETWEEN the existing dots, so the layers stop being one field at
     several strengths and become overlapping grids — and grids of
     different pitch beat into a plaid you can see at a glance. */
  .ag-effort-track .dots{
    background:var(--paper-2);overflow:hidden;
    background-image:radial-gradient(circle at center,
      color-mix(in srgb,var(--accent) 42%,transparent) 17%, transparent 19%);
    background-size:4px 4px;
    -webkit-mask-image:linear-gradient(90deg,rgba(0,0,0,.13) 0%,rgba(0,0,0,.44) 42%,#000 88%);
    mask-image:linear-gradient(90deg,rgba(0,0,0,.13) 0%,rgba(0,0,0,.44) 42%,#000 88%)}
  .ag-effort-track .dots::before{
    background-image:radial-gradient(circle at center,
      color-mix(in srgb,var(--accent) 66%,transparent) 18%, transparent 20%);
    background-size:4px 4px;
    -webkit-mask-image:linear-gradient(90deg,transparent 14%,rgba(0,0,0,.5) 52%,#000 88%);
    mask-image:linear-gradient(90deg,transparent 14%,rgba(0,0,0,.5) 52%,#000 88%)}
  .ag-effort-track .dots::after{
    background-image:radial-gradient(circle at center,
      var(--accent) 19%, transparent 21%);
    background-size:4px 4px;
    -webkit-mask-image:linear-gradient(90deg,transparent 48%,rgba(0,0,0,.45) 76%,#000 100%);
    mask-image:linear-gradient(90deg,transparent 48%,rgba(0,0,0,.45) 76%,#000 100%)}

  /* ── THE CHARGE ───────────────────────────────────────────────────────
     Max only, and it fills in rather than switching on.

     A MASK, NOT A CLIP. clip-path did the job but its edge is a hard
     vertical line, and a hard line travelling across a track reads as a
     progress bar filling — mechanical, and the one thing this should not
     look like. The mask carries a soft falloff about a third of the track
     wide, so what moves is a gradient shoulder rather than a cut, and the
     band appears to soak across instead of being wiped in.

     The geometry: the mask is 240% of the element, opaque to 42% of its own
     width and transparent by 56%. At mask-position 100% the element shows
     the image's last 41.67%, which is entirely past the fade — fully
     hidden. At 0% it shows the first 41.67%, entirely inside the opaque
     run — fully lit. Sliding between the two therefore reveals left to
     right, the direction the scale reads, with the shoulder sweeping
     across. Both numbers matter: a shorter mask leaves the charged state
     faded at its right edge, a longer one starts already partly visible.

     No transition on the way out. Dragging off Max drops it immediately,
     which is correct: the band means "this one setting", and a band fading
     away over a third of a second while you are already on Smart is the
     band lying about the level. */
  .ag-effort-track .fill{
    position:absolute;inset:0;border-radius:8px;pointer-events:none;z-index:1;
    opacity:0;
    /* Eight stops rather than four. The ramp is the full width of a small
       control, so four left visible steps between them; at this count the
       transition between any two is under the threshold where an edge
       shows. The 180deg layer on top is a single soft highlight along the
       upper edge, which is what stops the band reading as flat ink. */
    background-image:
      linear-gradient(180deg,rgba(255,255,255,.13),rgba(255,255,255,0) 62%),
      linear-gradient(90deg,
        transparent 0%,
        color-mix(in srgb,var(--accent) 4%,transparent) 14%,
        color-mix(in srgb,var(--accent) 11%,transparent) 28%,
        color-mix(in srgb,var(--accent) 21%,transparent) 42%,
        color-mix(in srgb,var(--accent) 34%,transparent) 56%,
        color-mix(in srgb,var(--accent) 47%,transparent) 70%,
        color-mix(in srgb,var(--accent) 58%,transparent) 85%,
        color-mix(in srgb,var(--accent) 66%,transparent) 100%);
    -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 42%,
      rgba(0,0,0,.72) 47%,rgba(0,0,0,.28) 52%,rgba(0,0,0,0) 56%);
    mask-image:linear-gradient(90deg,#000 0%,#000 42%,
      rgba(0,0,0,.72) 47%,rgba(0,0,0,.28) 52%,rgba(0,0,0,0) 56%);
    -webkit-mask-size:240% 100%;mask-size:240% 100%;
    -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
    -webkit-mask-position:100% 0;mask-position:100% 0}
  /* Eased at BOTH ends. A pure ease-out leaves at full speed from a
     standing start, which is the abrupt part of a wipe however soft its
     edge; this leans in, runs, and settles. */
  .ag-effort-track[data-heat="max"] .fill{
    opacity:1;animation:effCharge 1.6s cubic-bezier(.4,0,.2,1) forwards}
  .ag-effort-track.dragging[data-heat="max"] .fill{animation-duration:.85s}
  @keyframes effCharge{
    from{-webkit-mask-position:100% 0;mask-position:100% 0}
    to{-webkit-mask-position:0% 0;mask-position:0% 0}
  }

  /* ── IN ARABIC ────────────────────────────────────────────────────────
     The scale runs right to left there — Faster on the right, Smarter on
     the left, and the thumb already goes to the left at Max — but the
     grain and the charge are gradients and mask positions, which i18n.js
     does not mirror. So the handle sat at "Smarter" while the dense end,
     the blue and the charge all stayed on "Faster". Mirrored here, by rules
     that name rtl so the stylesheet mirror leaves them alone. The grain and
     the charge are flipped whole — nothing inside them moves by translate.
     The particles are not: their bright head runs on translateX, which the
     mirror already reverses, so only their masks turn round, and the head's
     own gradient so its bright edge leads. The sheen is mirrored already. */
  [dir="rtl"] .ag-effort-track .dots,
  [dir="rtl"] .ag-effort-track .fill{transform:scaleX(-1)}
  [dir="rtl"] .ag-effort-track .particles{
    -webkit-mask-image:linear-gradient(270deg,transparent 22%,rgba(0,0,0,.5) 52%,#000 92%);
    mask-image:linear-gradient(270deg,transparent 22%,rgba(0,0,0,.5) 52%,#000 92%)}
  [dir="rtl"] .ag-effort-track .particles::before{
    -webkit-mask-image:linear-gradient(270deg,transparent 34%,rgba(0,0,0,.4) 62%,#000 100%);
    mask-image:linear-gradient(270deg,transparent 34%,rgba(0,0,0,.4) 62%,#000 100%)}
  [dir="rtl"] .ag-effort-track .particles::after{
    background:linear-gradient(270deg,transparent,rgba(255,255,255,.28) 38%,
      rgba(255,255,255,.92) 62%,rgba(255,255,255,.55) 78%,transparent)}

  /* ── THE FIELD ────────────────────────────────────────────────────────
     Light speckle and a bright head, both of which live ON the charge — a
     white mote over the bare ground is invisible, so this is Max-only too.
     It has to be: the charge is what these are texture and motion FOR. */
  .ag-effort-track .particles{
    position:absolute;inset:0;border-radius:8px;overflow:hidden;
    pointer-events:none;z-index:2;opacity:0;
    /* No transition on opacity, because the field is either on or off and
       a fade buys nothing: it belongs to Max alone, and the charge beneath
       it is already the thing that arrives gradually.

       An earlier comment here claimed a transition on this property "sticks
       because the popover subtree is hidden". That was wrong, and it is
       worth saying so rather than deleting it: the measurement behind it
       was taken in a browser tab that was not painting, where every
       animation clock is throttled to a standstill - a plain <div> created
       on the spot showed currentTime 0 after 900ms and rAF fired once in
       800ms. Nothing about this element is special. Anyone re-measuring
       animation timing on this page should check document.visibilityState
       and rAF cadence first. */
    background-image:radial-gradient(circle at center,
      rgba(255,255,255,.55) 16%,transparent 18%);
    background-size:4px 4px;
    background-position:0 0;
    -webkit-mask-image:linear-gradient(90deg,transparent 22%,rgba(0,0,0,.5) 52%,#000 92%);
    mask-image:linear-gradient(90deg,transparent 22%,rgba(0,0,0,.5) 52%,#000 92%);
    animation:effDrift 4s linear infinite}
  .ag-effort-track[data-heat="max"] .particles{opacity:1}
  .ag-effort-track.dragging[data-heat="max"] .particles{animation-duration:1.7s}
  /* Exactly one cell, so it loops seamlessly and the motion reads as the
     grain travelling rather than the whole panel sliding. */
  @keyframes effDrift{ to{background-position:4px 0} }

  /* Motes flickering on a period that does not divide the drift's, so the
     two never line up into a single pulse. */
  .ag-effort-track .particles::before{
    content:"";position:absolute;inset:0;
    background-image:radial-gradient(circle at center,
      rgba(255,255,255,.8) 15%,transparent 17%);
    background-size:4px 4px;
    -webkit-mask-image:linear-gradient(90deg,transparent 34%,rgba(0,0,0,.4) 62%,#000 100%);
    mask-image:linear-gradient(90deg,transparent 34%,rgba(0,0,0,.4) 62%,#000 100%);
    animation:effTwinkle 2.6s ease-in-out infinite}
  @keyframes effTwinkle{ 0%,100%{opacity:.16} 50%{opacity:.66} }

  /* THE HEAD. A bright leading edge with a tail behind it. Its first pass
     is timed to the charge - same 1.6s, both starting the moment the level
     becomes Max - so the light arrives and the band is left behind it. It
     keeps looping after that, which is what stops a charged track looking
     like a finished progress bar.

     Linear on purpose: an eased sweep reads as a shine passing over glass,
     a constant one reads as something moving under its own power. */
  .ag-effort-track .particles::after{
    content:"";position:absolute;top:-2px;bottom:-2px;width:15%;
    background:linear-gradient(90deg,
      transparent,
      rgba(255,255,255,.28) 38%,
      rgba(255,255,255,.92) 62%,
      rgba(255,255,255,.55) 78%,
      transparent);
    filter:blur(1.5px);
    transform:translateX(-200%);opacity:0}
  .ag-effort-track[data-heat="max"] .particles::after{
    opacity:1;animation:effRun 1.6s linear infinite}
  .ag-effort-track.dragging[data-heat="max"] .particles::after{animation-duration:.95s}
  @keyframes effRun{
    0%{transform:translateX(-200%)}
    100%{transform:translateX(800%)}
  }

  /* At the top the track itself is lit, not just its contents. Max only,
     for the same reason as everything else here. */
  .ag-effort-track .dots{transition:box-shadow .35s var(--ease)}
  .ag-effort-track[data-heat="max"] .dots{
    box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 26%,transparent),
      0 0 15px -2px color-mix(in srgb,var(--accent) 55%,transparent)}

  /* The slow ambient sheen, under the head and over the charge. It is drawn
     in accent, so like everything else blue here it is Max only - at the
     lower levels it was a blue wash crossing a track that is supposed to
     have no blue in it at all. */
  .ag-effort-track .sheen{position:absolute;inset:0;border-radius:8px;overflow:hidden;
    pointer-events:none;z-index:3;opacity:0}
  .ag-effort-track[data-heat="max"] .sheen{opacity:1}
  .ag-effort-track .sheen::after{content:"";position:absolute;top:0;bottom:0;width:38%;
    background:linear-gradient(100deg,transparent,
      color-mix(in srgb,var(--accent) 26%,transparent) 45%,transparent);
    transform:translateX(-140%);
    animation:effSheen 4.4s cubic-bezier(.4,0,.2,1) infinite}
  @keyframes effSheen{
    0%{transform:translateX(-140%)}
    60%{transform:translateX(300%)}
    100%{transform:translateX(300%)}
  }

  /* The visible thumb is a div so it can EASE between steps. A native range
     thumb jumps: the browser paints it at the new value on the same frame,
     so arrow keys and taps both snap. The input is still the control — it
     keeps focus, keyboard and touch — with its own thumb made transparent
     and left full height for the hit area. */
  .ag-effort-thumb{position:absolute;top:50%;left:0;width:24px;height:20px;border-radius:7px;
    /* NO CUSTOM PROPERTY IN HERE — the transform is written from JS.
       Two attempts went through a variable and both failed silently while
       every diagnostic said they should work: calc(var(--n) * var(--len))
       computed to zero, and a single var(--eff-x) latched at whatever value
       it first held. Measured across five steps the thumb reported x=119
       while --eff-x read 0, 59, 119 and 178 in turn — the property updates,
       the transform does not follow it. An unregistered custom property
       inside transform is not a reliable dependency for style recalc here,
       so positionThumb() assigns the whole declaration instead. The
       transition below still does the easing. */
    /* POSITIONED WITH `left`, NOT `transform`.
       Three attempts went through transform and all three failed the same
       way: the computed matrix stayed at one value no matter what was
       written. Measured directly — setting style.transform to
       translate(0px,-50%), even with !important, still rendered at 172px,
       and there was no competing rule and no animation on the element. The
       cause was never identified; `left` is not subject to it, transitions
       identically, and the vertical centring keeps a static transform. */
    transform:translateY(-50%);
    background:#fff;border:1px solid rgba(23,23,23,.16);
    box-shadow:0 1px 3px rgba(23,23,23,.22);
    pointer-events:none;z-index:3;
    transition:left .26s cubic-bezier(.22,1,.28,1),box-shadow .24s var(--ease)}
  /* The halo is the level rather than decoration, so it is a class the two
     top levels carry — driven from JS, which already knows the level, rather
     than from a custom property inside a shadow. */
  .ag-effort-track[data-heat="smart"] .ag-effort-thumb{
    box-shadow:0 1px 3px rgba(23,23,23,.22),0 0 8px color-mix(in srgb,var(--accent) 34%,transparent)}
  .ag-effort-track[data-heat="max"] .ag-effort-thumb{
    box-shadow:0 1px 3px rgba(23,23,23,.22),0 0 13px color-mix(in srgb,var(--accent) 52%,transparent)}
  /* Dragging AT max: the halo gains a hard ring as well as the bloom, so the
     handle reads as charged rather than merely glowing. */
  .ag-effort-track.dragging[data-heat="max"] .ag-effort-thumb{
    box-shadow:0 1px 3px rgba(23,23,23,.22),
      0 0 0 3px color-mix(in srgb,var(--accent) 26%,transparent),
      0 0 18px color-mix(in srgb,var(--accent) 72%,transparent)}
  /* No easing while dragging — a 260ms ease chasing a pointer trails behind
     it, which reads as stutter rather than as smoothness. */
  .ag-effort-track.dragging .ag-effort-thumb{transition:box-shadow .24s var(--ease)}
  .ag-effort-track.dragging .ag-effort-thumb{left:var(--x,0)}
  :root[data-theme="dark"] .ag-effort-thumb{background:#f6f6f8;border-color:rgba(0,0,0,.45);
    box-shadow:0 1px 4px rgba(0,0,0,.6)}
  .ag-effort-range:focus-visible ~ .ag-effort-thumb{
    box-shadow:0 1px 3px rgba(23,23,23,.26),0 0 0 3px color-mix(in srgb,var(--accent) 32%,transparent)}
  .ag-effort-track:active .ag-effort-thumb{transition-duration:.1s}

  .ag-effort-range{position:absolute;inset:0;width:100%;height:100%;margin:0;z-index:4;
    -webkit-appearance:none;appearance:none;background:transparent;cursor:pointer}
  .ag-effort-range:focus{outline:none}
  .ag-effort-range::-webkit-slider-runnable-track{height:26px;background:transparent}
  .ag-effort-range::-moz-range-track{height:26px;background:transparent}
  .ag-effort-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
    width:24px;height:26px;background:transparent;border:0}
  .ag-effort-range::-moz-range-thumb{width:24px;height:26px;background:transparent;border:0}

  /* The same hint the reference carries: enter commits and closes. */
  .ag-effort-enter{flex:none;width:15px;height:15px;color:var(--mut);opacity:.5}

  @media (prefers-reduced-motion:reduce){
    /* Reduced motion means no motion, not no control. This group used to be
       display:none in one rule - pill, popover, thumb and all - so anyone
       with the OS setting on lost the ability to change effort at all
       rather than losing the animation. The control stays; its transitions
       and animations do not. */
    .ag-effort-pop,.ag-effort-tip,.ag-effort-head .v,.ag-effort-thumb,
    .ag-effort-pill,.ag-effort-track .dots{transition:none;animation:none}
    /* These exist only in order to move, so there is nothing left of them
       to keep. The charge goes with them: a band that is supposed to arrive
       is not worth having if it cannot. */
    .ag-effort-track .fill,
    .ag-effort-track .particles,
    .ag-effort-track .sheen{display:none}
  }
  @media (max-width:900px){
    /* Anchor to the COMPOSER, not the pill and not the viewport.
       Pill-anchored, the popover started at -65px on a 375px screen —
       measured, with Faster off the left edge. Viewport-anchored was worse
       in a way that only showed on the new-chat screen, where the composer
       is centred in the hero rather than pinned to the bottom, so it landed
       below the composer on top of the tiles. Making the wrap static hands
       the containing block to .ag-box, which is already position:relative
       and is the thing this should track. */
    .ag-effort-wrap{position:static}
    /* Still 252px, still pinned to the right edge.
       This used to be left:0;right:0;width:auto, which fixed the
       positioning by letting the panel stretch the whole width of the
       composer — so the same control was a neat card on a laptop and a
       full-width band on anything narrower, with its slider stretched to
       match. Pinning one edge and capping the width keeps the geometry
       identical everywhere; the min() is only there so it cannot overflow
       a composer narrower than the panel itself. */
    .ag-effort-pop{left:auto;right:0;width:min(252px, 100%);bottom:calc(100% + 10px);transform-origin:100% 100%}
    .ag-effort-tip{display:none}
  }

  /* The chrome moved to .ag-usagepop — this is the contents of a panel now,
     not a tile in a rail. The accent hover wash went with it: inside
     something already raised on its own shadow it read as a hover target
     that does nothing, and the comment that used to sit here measured it
     against "a 238px rail" that no longer surrounds it. */
  .ag-usage{display:flex;flex-direction:column;gap:11px}
  .ag-usage .u-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
  .ag-usage .u-plan{font-size:.78rem;font-weight:600;color:var(--ink);text-transform:capitalize}
  /* Mixed toward --ink rather than the bare --accent. On the tinted card
     the raw accent came to 4.23:1 in dark and 2.34:1 in light, both under
     AA for text this size - the light figure was already failing before
     the tint, the dark one is the tint's doing. Mixing deepens it on the
     pale card and lifts it on the dark one, from one declaration. */
  .ag-usage .u-up{font-size:.72rem;font-weight:600;text-decoration:none;
    color:color-mix(in srgb,var(--accent) 58%,var(--ink));
    display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
  .ag-usage .u-up:hover{text-decoration:underline}
  .ag-usage .u-up svg{width:12px;height:12px}
  .u-row{display:flex;flex-direction:column;gap:4px}
  .u-lab{display:flex;align-items:baseline;justify-content:space-between;gap:8px;
    font-size:.76rem;color:var(--ink-2)}
  .u-lab b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
  .u-bar{height:6px;border-radius:99px;background:color-mix(in srgb,currentColor 12%,transparent);
    overflow:hidden;color:var(--ink-2)}
  .u-bar i{display:block;height:100%;border-radius:99px;background:var(--accent);
    width:0;transition:width var(--dur-chill,.3s) var(--ease-snappy,ease-out)}
  .u-bar i.warn{background:var(--warn)}
  .u-bar i.hot{background:var(--danger)}
  .u-when{font-size:.67rem;color:var(--mut);font-variant-numeric:tabular-nums}
  .u-row.quiet .u-lab,.u-row.quiet .u-when{color:var(--mut)}
  @media (prefers-reduced-motion:reduce){ .u-bar i{transition:none} }

  /* Laid out the way Claude's own usage popover does it: the limit's name
     on the left, and its reset time and percentage together on the right
     of the SAME line, with the bar under both. Reading "how full" and
     "when does it clear" as one line is the whole point — they are the
     two halves of one question, and splitting the reset onto its own row
     below the bar (which is what this did before) made it read as a
     footnote to the bar rather than as half the answer. */
  /* Tuned for a 194px rail when it lived in one. A ~300px panel has room
     for the name in full and the reset time beside the number, which is the
     shape this row was always reaching for. */
  .u-lab{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
    font-size:.775rem;color:var(--ink);width:100%}
  .u-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:none;font-weight:550}
  /* Claude has a 460px popover for this line; the rail has 194px. At the
     worst case it actually has to render - "5-hour limit / Resets in 2h37m
     / 100%" - the three parts came to 2px under the width, and the part
     that gave way was the LABEL, so the row read "5-hour limi...". Wrong
     one: the label is what the row is about, the countdown is the detail.
     So the label is flex:none, and the countdown is what truncates. */
  .u-meta{display:flex;align-items:baseline;gap:7px;flex:0 1 auto;min-width:0}
  /* --ink-2, not --mut. On the untinted card --mut already only managed
     3.58:1 against it; the accent wash took that to 2.90, which is under
     AA for text this size. --ink-2 puts it back to 4.61. The hierarchy
     still holds - the percentage beside it is --ink and bold. */
  .u-reset{color:var(--mut);font-size:.72rem;white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis;min-width:0}
  .u-meta b{flex:none}
  .u-lab b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}

/* ARABIC: the arrows in and around the composer point along the line of
   reading. Drawn left-to-right, they kept pointing right in Arabic, where
   "next" is leftward: the effort popover's ↵ hint, the "Other providers →
   Settings" arrow in the mode menu, and "Detailed usage →" in the usage
   panel — that last one a glyph in ::after, which no mirror can reach. */
[dir="rtl"] .ag-effort-enter,
[dir="rtl"] .pop-more .st svg{transform:scaleX(-1)}
[dir="rtl"] .u-more::after{content:" \2190"}

/* The row keeps its English order in Arabic: .ag-brow carries dir="ltr" on
   /agent and the home page, so + stays at the start and send at the end
   instead of trading places. The two menus inside it stay Arabic — their
   mirrored rules and composer-controls.js both read the direction — and
   are anchored where English anchors them, under the pill's right edge.
   Selectors naming dir are ones i18n.js does not mirror. */
:root[dir="rtl"] .ag-brow .ag-effort-pop,
:root[dir="rtl"] .ag-brow .ag-model-popover{direction:rtl}
.ag-brow[dir="ltr"] .ag-effort-pop{left:auto;right:0;transform-origin:100% 100%}
.ag-brow[dir="ltr"] .ag-model-popover{left:auto;right:0}
