/* Range-bar marks — the single home for how a value is drawn against a target range.
   Values come from design-tokens.css; this file is the grammar that uses them.

   Every mark here encodes a fact about the data, so none of them may vary between screens:
   the faded zone edge says the bound is soft by MacroAcceptanceTolerance, the notch says
   where the bound is, the grey continuation distinguishes a fill that passed the ceiling
   from one that landed on it. What MAY vary is scale — set --rb-track-height per host.

   A second home for any of these values is how the last divergence happened: the compare
   bars kept a dashed-border zone for months after the canvas moved to a faded one. */

.rb-bar {
  --rb-track-height: 9px;
  /* A span with a height and no display is an inline box, and height does not apply to one.
     It has worked so far only because its host happens to be flex; the compare bars adopt this
     file next and their host may not be. */
  display: block;
  position: relative;
  height: var(--rb-track-height);
  border-radius: 999px;
  background: var(--fs-bg-tertiary);
}

/* The shaded band between the bounds. Fades at both ends; a one-sided range simply runs to
   the edge it has no bound on, and the modifiers below drop that side's fade with it. */
.rb-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--rb-zone-color) var(--fs-range-zone-fade),
    var(--rb-zone-color) calc(100% - var(--fs-range-zone-fade)),
    transparent 100%
  );
}

/* Open at the start: no floor, so nothing to fade in from. */
.rb-zone--open-start {
  border-radius: 999px 0 0 999px;
  background: linear-gradient(
    90deg,
    var(--rb-zone-color) 0%,
    var(--rb-zone-color) calc(100% - var(--fs-range-zone-fade)),
    transparent 100%
  );
}

/* Open at the end: no ceiling, so the band runs to the track's end. */
.rb-zone--open-end {
  border-radius: 0 999px 999px 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--rb-zone-color) var(--fs-range-zone-fade),
    var(--rb-zone-color) 100%
  );
}

/* The value. Full track height: a notch has to cut the whole fill to read as a bound, and an
   inset fill leaves the notch floating above it. */
.rb-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 999px;
  background: var(--rb-fill-color);
}

/* Logging a food is the core loop and this bar is the only feedback above the fold on mobile;
   without a transition it teleports on re-render and nothing signals that the tap landed. */
@media (prefers-reduced-motion: no-preference) {
  /* The zone and its notches too: the wash spans the zone, so a zone or a bound that jumped while
     the wash slid would leave them out of step for the slide (#3862). */
  .rb-zone,
  .rb-notch,
  .rb-fill,
  .rb-overshoot,
  .rb-wash {
    transition:
      width 0.25s ease,
      left 0.25s ease;
  }
}

/* Squared off where the grey takes over, so the two read as one continuous bar. */
.rb-fill--continues {
  border-radius: 999px 0 0 999px;
}

/* Past the ceiling. Never red. */
.rb-overshoot {
  position: absolute;
  top: 0;
  bottom: 0;
  /* Clear the ceiling notch. The notch straddles the bound, so it covers the first 1px of any
     overshoot (2px wide, offset half its width): 50 kcal over a 2200 ceiling is 3.6px on a
     200px strip and simply vanished, making "just over" and "exactly on it" identical. Three
     notch-widths is more than that needs — the surplus is deliberate, so the arrowhead has
     something to sit on rather than being a sliver. */
  min-width: calc(var(--fs-range-notch-width) * 3);
  border-radius: 0 999px 999px 0;
  background: var(--fs-range-overshoot);
}

/* Food the day still adds (#3194), after the planned food: stripes in the fill colour up to the limit, grey past it. Text carries the meaning. */
.rb-stripe {
  position: absolute;
  top: 0;
  bottom: 0;
  background: repeating-linear-gradient(135deg, var(--rb-fill-color) 0 2px, transparent 2px 4px);
}

.rb-stripe--past {
  background: repeating-linear-gradient(135deg, var(--fs-range-overshoot) 0 2px, transparent 2px 4px);
}

/* Ran off the end of the track. The arrowhead says "and beyond", which a flat end cannot.
   On a floor-only row this takes the macro colour instead — passing a floor is not going
   over range — which the markup does by pointing it at .rb-fill rather than .rb-overshoot. */
.rb-terminus {
  /* No radius of its own: the polygon removes the pointed end, and each host keeps the left
     end it should have — round on the fill, which starts at the track's own edge, square on
     the overshoot, which butts against the fill. */
  clip-path: polygon(
    0 0,
    calc(100% - var(--fs-range-terminus)) 0,
    100% 50%,
    calc(100% - var(--fs-range-terminus)) 100%,
    0 100%
  );
}

/* A bound. Sits ABOVE the fill: drawn underneath, a bar at or past its ceiling erases its
   own range exactly where the range matters most. */
.rb-notch {
  position: absolute;
  /* Overhangs the track rather than sitting inside it, and that is what makes a solid mark
     workable. The previous answer was a white core with a ring, but a 1px ring around a 2px×12px
     box closes on all four sides and reads as a bracket glyph — "[]" — not a goal line.
     Nothing wins on contrast INSIDE the track: dark loses to the dark calories fill, light loses
     to the pale track. So the ends do the work — they are always against the page — and the
     crossing is just continuity. Fixed length, not a percentage: 25% left a 6px macro track
     with 1.5px of mark outside the bar, which is not a mark. */
  top: calc(var(--fs-range-notch-overhang) * -1);
  bottom: calc(var(--fs-range-notch-overhang) * -1);
  width: var(--fs-range-notch-width);
  /* Straddle the bound rather than starting at it. Offset to the right, the ceiling notch
     lands in the overshoot's first two pixels and never cuts the fill, so the two bounds get
     marked asymmetrically — the floor reads "here" and the ceiling reads "just past". */
  margin-left: calc(var(--fs-range-notch-width) / -2);
  background: var(--fs-range-notch-color);
  border-radius: 1px;
  z-index: 1;
}

/* The zone's second material. Same band, same edges, same extent — but where the fill is
   underneath, the tint has nothing to be pale against, so lightness carries it instead. White
   at low alpha is the one channel that survives all four macro colours AND the dark calories
   fill, where darkening would fail.

   Sits above the fill and below the notches. Without it the band appeared to be eaten from the
   left as the day filled, reading as "how much of my range is left" rather than "where my range
   is" — and it disappeared completely at on target and over, the two states the range exists
   for. In the over state the band is now at full width exactly where it matters most. */
.rb-wash {
  --rb-wash-color: var(--fs-bg-primary-a30); /* white over a light-mode fill, dark over a dark-mode one */
  --rb-wash-fade: calc(
    var(--fs-range-zone-fade) * var(--rb-wash-fade-scale, 1)
  );
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--rb-wash-color);
}

/* Both edges are bounds — the fill has passed the ceiling, so the wash spans the whole zone. */
.rb-wash--fade-both {
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--rb-wash-color) var(--rb-wash-fade),
    var(--rb-wash-color) calc(100% - var(--rb-wash-fade)),
    transparent 100%
  );
}

/* Left edge is the floor and fades; the right is where the value stopped, and stops hard. */
.rb-wash--fade-start {
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--rb-wash-color) var(--rb-wash-fade),
    var(--rb-wash-color) 100%
  );
}

/* No floor to fade in from — a ceiling-only row is in range from the very start of the track,
   so it takes the fill's own left cap the way the flat case does. */
.rb-wash--fade-end {
  border-radius: 999px 0 0 999px;
  background: linear-gradient(
    90deg,
    var(--rb-wash-color) 0%,
    var(--rb-wash-color) calc(100% - var(--rb-wash-fade)),
    transparent 100%
  );
}

/* Where the wash ends on the fill's own end it takes the fill's cap, so it does not overhang
   the rounded terminus underneath. */
.rb-wash--cap-end {
  border-radius: 0 999px 999px 0;
}

.rb-wash--cap-both {
  border-radius: 999px;
}

/* Windows contrast themes (forced colours, #3697): the browser paints every background as the page
   colour, so the track, zone, fill and notches all vanished. Same grammar in two colours — the text
   colour and the page colour — with shape doing what hue did (Claude Design, project 51132ddb).
   --rb-shaft is the overshoot's thickness: a third of the track, so 3px on the 9px track and 2px on
   the phone's 6px one, always thinner than the 1px-inset fill beside it. */
@media (forced-colors: active) {
  .rb-bar {
    --rb-shaft: calc(var(--rb-track-height) / 3);
    isolation: isolate;
  }

  /* The outline is a layer rather than the bar's own outline, so the notches can cut through it. */
  .rb-bar::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    border: 1px solid CanvasText;
    border-radius: inherit;
  }

  .rb-zone,
  .rb-fill,
  .rb-overshoot,
  .rb-wash,
  .rb-stripe,
  .rb-notch {
    forced-color-adjust: none;
  }

  /* Hard edges: the fade has no system colour to fade through; the notch carries the bound. */
  .rb-zone,
  .rb-zone--open-start,
  .rb-zone--open-end {
    top: 1px;
    bottom: 1px;
    background: repeating-linear-gradient(45deg, CanvasText 0 1px, transparent 1px 4px);
  }

  .rb-fill {
    top: 1px;
    bottom: 1px;
    background: CanvasText;
  }

  /* The same hatch in the page colour. The wash has the zone's left, top and bottom, so a 45deg
     gradient anchored at the bottom-left corner starts in the same phase: the zone's lines run on
     across the fill as gaps in it. */
  .rb-wash,
  .rb-wash--fade-both,
  .rb-wash--fade-start,
  .rb-wash--fade-end {
    top: 1px;
    bottom: 1px;
    background: repeating-linear-gradient(45deg, Canvas 0 1px, transparent 1px 4px);
  }

  /* A floor-only fill that runs off the track is cut to the arrowhead; so is the wash on it. */
  .rb-fill.rb-terminus ~ .rb-wash--cap-end {
    border-radius: 0;
    clip-path: polygon(
      0 0,
      calc(100% - var(--fs-range-terminus)) 0,
      100% 50%,
      calc(100% - var(--fs-range-terminus)) 100%,
      0 100%
    );
  }

  /* Past the limit the bar narrows to a shaft. Shape says "over", not a grey. */
  .rb-overshoot {
    top: var(--rb-shaft);
    bottom: var(--rb-shaft);
    border-radius: 0 2px 2px 0;
    background: CanvasText;
  }

  .rb-overshoot.rb-terminus {
    clip-path: none;
    border-radius: 0;
  }

  /* Full-height arrowhead (to the outline) on the shaft's end. */
  .rb-overshoot.rb-terminus::after {
    content: "";
    position: absolute;
    right: 0;
    top: calc(1px - var(--rb-shaft));
    bottom: calc(1px - var(--rb-shaft));
    width: var(--fs-range-terminus);
    background: CanvasText;
    clip-path: polygon(0 0, 100% 50%, 0 100%);
  }

  /* Still to come: 2px on, 2px off, on the page colour so the zone's hatch does not cross it. */
  .rb-stripe {
    top: 1px;
    bottom: 1px;
    box-shadow: inset 1px 0 0 Canvas;
    background: repeating-linear-gradient(135deg, CanvasText 0 2px, transparent 2px 4px) Canvas;
  }

  .rb-stripe--past {
    top: var(--rb-shaft);
    bottom: var(--rb-shaft);
    box-shadow: none;
    background: repeating-linear-gradient(135deg, CanvasText 0 2px, transparent 2px 4px);
  }

  /* 2px of ink between 1px page-colour gaps, above everything, the outline included. */
  .rb-notch {
    z-index: 3;
    box-sizing: border-box;
    border-radius: 0;
    width: calc(var(--fs-range-notch-width) + 2px);
    margin-left: calc(var(--fs-range-notch-width) / -2 - 1px);
    border-inline: 1px solid Canvas;
    background: CanvasText;
    background-clip: padding-box;
  }
}
