/*
 * Avatar Gradient
 *
 * Measured from Figma `Avatar Gradient` (1054:305), re-read after the
 * 2026-08-28 redesign. Circle only — the set has no Shape axis, because a
 * gradient this directional does not survive a corner.
 *
 * Sizes and the type ramp are Avatar's, including regular weight at Mini:
 *
 *   mini    24   type 12/18 regular
 *   small   32   type 14/20 medium
 *   medium  40   type 16/24 medium
 *   large   48   type 20/32 medium
 *
 * IT USED TO BE THE OTHER WAY UP, AND THE CONTRAST GATE IS WHY IT IS NOT
 *
 * The first version was a saturated disc — `color/<hue>/500` to `/600` — with
 * white initials. Four of the seven failed WCAG AA at 3.5 to 3.8:1, and the fix
 * was made in Figma rather than here: the disc is now a pale tint and the
 * initials carry the colour. Do not "restore" the saturated version. It is not
 * a style preference that changed.
 *
 * THREE RUNGS, THREE TOKENS
 *
 *   0%    color/<hue>/300   the deepest tint, at the TOP
 *   60%   color/<hue>/200
 *   100%  color/<hue>/50    nearly white, at the bottom
 *
 * Every stop is variable-bound in Figma, so all three are real tokens and the
 * `color-mix` midpoint the old two-rung version needed is gone. Slate is the
 * gray ramp; every other colour is its own hue at the same three rungs, which
 * is what makes this a system rather than seven pictures.
 */
.ion-avatar-gradient {
  --ion-avatar-gradient-size: var(--spacing-40);
  --ion-avatar-gradient-font-size: var(--type-body);
  --ion-avatar-gradient-line-height: var(--type-body-line-height);
  --ion-avatar-gradient-font-weight: var(--font-weight-medium);

  /* Slate, which is also the block default — Figma's default variant. */
  --ion-avatar-gradient-from: var(--surface-palette-1);
  --ion-avatar-gradient-mid: var(--surface-palette-1-tint);
  --ion-avatar-gradient-to: var(--surface-palette-1-subtle);

  /*
   * The initials. THIS USED TO READ FROM THE PRIMITIVE RAMP, AND THE COMMENT
   * HERE DEFENDED IT — correctly, on its own terms: the disc was primitives, so
   * a semantic foreground would have flipped in the dark theme and left the
   * background alone. An earlier draft did exactly that and the gate caught it
   * at 1.05:1. A foreground has to theme exactly as much as the ground under it.
   *
   * That argument was right and the conclusion was wrong. It resolved the
   * mismatch by theming NEITHER, which made the whole component theme-blind:
   * seven near-white discs (luminance 0.89 to 0.98) rendered unchanged in the
   * dark theme, because Primitives and Semantics each hold one mode and only
   * Interface carries a Light/Dark axis. Nothing here was bound to Interface,
   * so nothing here listened to the theme.
   *
   * Both ends now theme together, which is what the original argument actually
   * asked for. See AGENTS.md for the ladder and the measurements.
   */
  --ion-avatar-gradient-text: var(--text-palette-1);

  /*
   * The sheen: a white radial highlight low and centre, over the linear
   * gradient. Identical in proportion at all four sizes — Figma expresses it as
   * a userSpaceOnUse radial scaled per size, and the ratios come out the same
   * to three decimals, so the geometry is written once as percentages.
   *
   * THE ALPHA IS A TOKEN NOW. It was a raw `18%` in both themes, hardcoded
   * twice, which is a place dark mode has to be fixed by hand — the same reason
   * the bevel below is a local. `surface/sheen` is 20% in Light and 5% in Dark,
   * following `surface/scrim` and `surface/hover`: a translucent wash whose
   * alpha themes.
   *
   * THE ACCESSIBILITY ARGUMENT THAT PUT IT AT 5% WAS WRONG, AND THIS COMMENT
   * USED TO MAKE IT. It claimed the gloss dropped five of seven hues under AA in
   * Dark — green 3.76, red 3.92, pink 4.08, orange 4.15, blue 4.23. Those
   * numbers came from compositing the sheen at FULL STRENGTH over the `from`
   * stop, and that pixel does not exist. `from` is the top of the disc; the
   * radial is centred at 70.513% of the height with a vertical radius of
   * 64.103%, so at y=0 it is 1.10 radii out — past its own transparent stop,
   * contributing nothing. The gloss and the darkest stop never meet.
   *
   * The gate evaluates the gradient geometrically as of 5 Sep 2026, and at the
   * authored 18% the worst REAL point in Dark is 5.07 (green, at 50%,69%, where
   * the gloss actually peaks and the disc beneath it is already near `to`).
   * Nothing was ever failing. 5% is an aesthetic choice, not a fix, and it is
   * only still here because it was reviewed in Figma and preferred.
   *
   * The worst point on this component is the bare top of the disc — 5.29 in
   * Light (pink) and 5.31 in Dark (red), the same two numbers the stop comment
   * below records, because the sheen never touches it.
   */

  /*
   * Bevel. Two inner shadows and no drop shadow — the redesign dropped the
   * lift, and these no longer scale with the box the way they did: Figma now
   * carries the same 1px / -2px offsets at all four sizes.
   *
   * A LOCAL, BECAUSE A RAW COLOUR IN A `box-shadow` DECLARATION IS BANNED — and
   * the ban is right. Its reason is that a raw colour is a place dark mode has
   * to be fixed by hand, once per occurrence; naming it here makes this file
   * exactly one such place instead of four, which is the same trade
   * `elevation.css` makes for the shared ramp. These are local Figma effects,
   * not effect STYLES, so they are not in that ramp and cannot be: the exporter
   * only sees named styles, and there is nothing here for it to name.
   */
  --ion-avatar-gradient-bevel:
    inset 0 -2px 4px 0 rgb(0 0 0 / 12%),
    inset 0 1px 1.4px 0 rgb(255 255 255 / 24%);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
  width: var(--ion-avatar-gradient-size);
  height: var(--ion-avatar-gradient-size);
  border-radius: var(--radius-full);
  color: var(--ion-avatar-gradient-text);

  /*
   * The flat colour under the gradient is the `to` end. It is the fallback if
   * `background-image` never paints, and that is the ONLY thing it is.
   *
   * THIS COMMENT USED TO CLAIM IT WAS ALSO THE WORST CASE FOR THE INITIALS, AND
   * THAT WAS BACKWARDS. Dark text on a pale disc is hardest to read against the
   * DARKEST stop, not the palest — `from`, not `to`. Because `verify-contrast`
   * can only see a flat `background-color`, it was measuring the most flattering
   * pairing of the three and calling it the strict one. Six of the seven hues
   * were failing AA against the `from` stop the whole time — blue 3.42, purple
   * 3.58, pink 3.27, orange 3.72, green 3.10, red 3.35 — and the build was green.
   *
   * The initials sit on `/800` in Light and `/200` in Dark, which mirror each
   * other about the ramp exactly as the three disc stops do (300/200/50 against
   * 700/800/900). They used to be `/600`, whose mirror is `/300` — the one rung
   * in the component that was not mirrored, which is precisely why Light failed
   * and Dark did not.
   *
   * THE GATE DOES NOT READ STOPS ANY MORE, IT EVALUATES THE GRADIENT. It began
   * by reading only a flat `background-color`, which is what let this hide; then
   * every stop; and as of 5 Sep 2026 it samples the disc, composites the layers
   * at each point and reports the worst pixel the element actually paints —
   * 5.29 in Light (pink) and 5.31 in Dark (red), both at 50%,0%, the bare top.
   * Colours BETWEEN two stops are real pixels and none of them were measured
   * before. Negative-tested by putting the initials back on `/600`: pink fails
   * at 3.27 where the old gate passed it.
   */
  background-color: var(--ion-avatar-gradient-to);
  background-image:
    radial-gradient(
      55.556% 64.103% at 50% 70.513%,
      var(--surface-sheen) 0%,
      var(--surface-sheen-subtle) 60%,
      transparent 100%
    ),
    linear-gradient(
      180deg,
      var(--ion-avatar-gradient-from) 0%,
      var(--ion-avatar-gradient-mid) 60%,
      var(--ion-avatar-gradient-to) 100%
    );
  box-shadow: var(--ion-avatar-gradient-bevel);
  font-family: var(--font-family-sans);
  font-size: var(--ion-avatar-gradient-font-size);
  line-height: var(--ion-avatar-gradient-line-height);
  font-weight: var(--ion-avatar-gradient-font-weight);
  user-select: none;
}

.ion-avatar-gradient--mini {
  --ion-avatar-gradient-size: var(--spacing-24);
  --ion-avatar-gradient-font-size: var(--type-caption);
  --ion-avatar-gradient-line-height: var(--type-caption-line-height);
  --ion-avatar-gradient-font-weight: var(--font-weight-regular);
}

.ion-avatar-gradient--sm {
  --ion-avatar-gradient-size: var(--spacing-32);
  --ion-avatar-gradient-font-size: var(--type-body-sm);
  --ion-avatar-gradient-line-height: var(--type-body-sm-line-height);
}

.ion-avatar-gradient--lg {
  --ion-avatar-gradient-size: var(--spacing-48);
  --ion-avatar-gradient-font-size: var(--type-body-lg);
  --ion-avatar-gradient-line-height: var(--type-body-lg-line-height);
}

/*
 * The seven colours. Each declares its own `color` and `background-color`
 * rather than inheriting them from the block: the contrast gate pairs what one
 * rule declares, and a colour it has to find on a different scope resolves
 * through the cascade to something that never renders together.
 *
 * All seven take `600`, including pink. It took `700` here until the 2026-08-28
 * primitive re-export, and that was not a design choice — the pink ramp shifted
 * down a rung, so the value this component wants (#c3135c) simply moved from
 * `700` to `600`. Renaming under a stable name is the failure the token
 * pipeline is built to catch; it caught this one.
 */
.ion-avatar-gradient--slate,
.ion-avatar-gradient--blue,
.ion-avatar-gradient--violet,
.ion-avatar-gradient--pink,
.ion-avatar-gradient--orange,
.ion-avatar-gradient--green,
.ion-avatar-gradient--red {
  color: var(--ion-avatar-gradient-text);
  background-color: var(--ion-avatar-gradient-to);
}

.ion-avatar-gradient--slate {
  --ion-avatar-gradient-from: var(--surface-palette-1);
  --ion-avatar-gradient-mid: var(--surface-palette-1-tint);
  --ion-avatar-gradient-to: var(--surface-palette-1-subtle);
  --ion-avatar-gradient-text: var(--text-palette-1);
}

.ion-avatar-gradient--blue {
  --ion-avatar-gradient-from: var(--surface-palette-2);
  --ion-avatar-gradient-mid: var(--surface-palette-2-tint);
  --ion-avatar-gradient-to: var(--surface-palette-2-subtle);
  --ion-avatar-gradient-text: var(--text-palette-2);
}

.ion-avatar-gradient--violet {
  --ion-avatar-gradient-from: var(--surface-palette-3);
  --ion-avatar-gradient-mid: var(--surface-palette-3-tint);
  --ion-avatar-gradient-to: var(--surface-palette-3-subtle);
  --ion-avatar-gradient-text: var(--text-palette-3);
}

.ion-avatar-gradient--pink {
  --ion-avatar-gradient-from: var(--surface-palette-4);
  --ion-avatar-gradient-mid: var(--surface-palette-4-tint);
  --ion-avatar-gradient-to: var(--surface-palette-4-subtle);
  --ion-avatar-gradient-text: var(--text-palette-4);
}

.ion-avatar-gradient--orange {
  --ion-avatar-gradient-from: var(--surface-palette-5);
  --ion-avatar-gradient-mid: var(--surface-palette-5-tint);
  --ion-avatar-gradient-to: var(--surface-palette-5-subtle);
  --ion-avatar-gradient-text: var(--text-palette-5);
}

.ion-avatar-gradient--green {
  --ion-avatar-gradient-from: var(--surface-palette-6);
  --ion-avatar-gradient-mid: var(--surface-palette-6-tint);
  --ion-avatar-gradient-to: var(--surface-palette-6-subtle);
  --ion-avatar-gradient-text: var(--text-palette-6);
}

.ion-avatar-gradient--red {
  --ion-avatar-gradient-from: var(--surface-palette-7);
  --ion-avatar-gradient-mid: var(--surface-palette-7-tint);
  --ion-avatar-gradient-to: var(--surface-palette-7-subtle);
  --ion-avatar-gradient-text: var(--text-palette-7);
}

/*
 * The disc is a gradient, and forced colours paint no background images: the
 * initials floated with nothing round them. A ring in the text colour draws
 * the circle, inside its edge so the size does not change.
 */
@media (forced-colors: active) {
  .ion-avatar-gradient {
    outline: var(--border-width-default) solid CanvasText;
    outline-offset: calc(-1 * var(--border-width-default));
  }
}
