/* The glow card and the live pieces that stand in it (Colour and glow, 2026-11-11: saas/DESIGN.md; decisions 3 and 4 of the premium
   design direction). Rebuilt in plain CSS on this product's tokens after the look of themeocean's "Interactive Tech Stack Bento Grid
   with Hover Effects" (21st.dev demo 43096, MIT: shared/NOTICE.md): the sizes of its three gradients, their strengths, the 26 px grid,
   the half-second fade. None of its code, classes, colours or markup is here. Tokens: accents.css (loaded before this sheet).

   THE CARD
     <article class="glow" data-accent="indigo"> ...ordinary markup... </article>
   .glow        the card of the product: its face (--glow-face), a dim 1 px edge (--glow-line, an inset ring, so no border and no
                box-shadow of its own), the radius (--glow-r, default the theme's card radius). Wherever a card stands on its own;
                never a table row or a field. Add .glow-pad for the bento's padding (20 px, 24 px from 640 px) and its column.
   .glow-fx     only the light, for an element that keeps its own face and edge (the site's older cards, marked by site.js).
   data-accent  the light's colour (accents.css); without it the emerald.
   The light: shared/js/glow.js, one listener for the page, sets .is-lit on the card under the pointer or the finger and writes
   --glow-x / --glow-y (px from the card's corner) on it. Three layers follow those two numbers:
     ::before   the edge: 240 px of the accent at --glow-ring, gone at 70 %, cut to the 1 px ring
     ::after    inside: 380 px of the accent at --glow-spot, gone at 65 %; under it the 26 px grid, shown only within 165 px of the
                pointer (a 220 px circle of the card's own face, clear in the middle and solid from 75 %, lies over the grid: so a
                .glow with another face sets --glow-face to it)
   Keyboard: focus inside the card lights it from its top edge. Touch: the finger lights it and it fades when the finger lifts.
   Reduced motion (the system's setting, or data-motion="off"): no light at all; the card is quiet and wears its accent on the edge.

   THE LIVE PIECES (built by shared/js/live.js; each reads --acc / --acc-rgb, so it takes the accent of the card it stands in)
     .live-badge > .live-dot          the "Live" dot, a slow pulse while it is on screen (Full motion only)
     .live-num                        a figure that counts (tabular numbers)
     .live-chart                      the smooth area line with its crosshair, point and tooltip
     .live-ring                       a score ring with its number and its label
     .live-bars > .live-bar           bars that grow from their baseline; .is-now is the newest
     .live-example                    the words "Example data" on a card whose numbers are not somebody's own
   Only transform and opacity move, each on one of the durations below; reduced motion shows every piece in its final state. */

:root {
  --glow-fade: 500ms;      /* the light arriving and leaving */
  --live-pulse: 1600ms;    /* one breath of the "Live" dot */
  --live-ring: 1200ms;     /* a score ring turning into place, once */
  --live-bar: 700ms;       /* a bar reaching a new value */
}

/* ==== the card ==== */
.glow, .glow-fx { --glow-x: 50%; --glow-y: 0%; position: relative; isolation: isolate; }
.glow { border-radius: var(--glow-r, var(--radius-lg, 22px)); background: var(--glow-face); box-shadow: inset 0 0 0 1px var(--glow-line); }
.glow-pad { display: flex; flex-direction: column; padding: 20px; }
@media (min-width: 640px) { .glow-pad { padding: 24px; } }

:is(.glow, .glow-fx)::before, :is(.glow, .glow-fx)::after { content: ""; position: absolute; pointer-events: none; opacity: 0;
  transition: opacity var(--glow-fade) var(--motion-ease-out, ease); }
/* the edge: the accent on the 1 px ring, brightest where the pointer is */
:is(.glow, .glow-fx)::before { inset: var(--glow-inset, 0px); z-index: 2; padding: 1px; border-radius: inherit;
  background: radial-gradient(240px circle at var(--glow-x) var(--glow-y), rgba(var(--acc-rgb, var(--acc-emerald-rgb)), var(--glow-ring)), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
/* inside: the soft spotlight, and under it the grid that shows only near the pointer */
.glow::after { inset: 1px; z-index: -1; border-radius: calc(var(--glow-r, var(--radius-lg, 22px)) - 1px);
  background:
    radial-gradient(380px circle at var(--glow-x) var(--glow-y), rgba(var(--acc-rgb, var(--acc-emerald-rgb)), var(--glow-spot)), transparent 65%),
    radial-gradient(220px circle at var(--glow-x) var(--glow-y), transparent, var(--glow-face) 75%),
    linear-gradient(var(--glow-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--glow-grid) 1px, transparent 1px);
  background-size: auto, auto, 26px 26px, 26px 26px; }
.glow-fx { --glow-inset: -1px; }
.glow-fx::after { inset: 0; z-index: -1; border-radius: inherit;
  background: radial-gradient(380px circle at var(--glow-x) var(--glow-y), rgba(var(--acc-rgb, var(--acc-emerald-rgb)), var(--glow-spot)), transparent 65%); }

/* lit: under the pointer or the finger (glow.js), or with the keyboard's focus inside */
:is(.glow, .glow-fx).is-lit::before, :is(.glow, .glow-fx).is-lit::after,
:is(.glow, .glow-fx):focus-visible::before, :is(.glow, .glow-fx):focus-visible::after { opacity: 1; }
@supports selector(:has(a)) {
  :is(.glow, .glow-fx):has(:focus-visible)::before, :is(.glow, .glow-fx):has(:focus-visible)::after { opacity: 1; }
}
@supports not selector(:has(a)) {
  :is(.glow, .glow-fx):focus-within::before, :is(.glow, .glow-fx):focus-within::after { opacity: 1; }
}

/* ==== the live pieces ==== */
.live-badge { display: inline-flex; align-items: center; gap: 6px; color: var(--acc-emerald); font-size: var(--a-t-xs, 12px); font-weight: 600;
  line-height: 1; white-space: nowrap; }
.live-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
/* the one motion here that does not end, and its reason is the live number beside it (decision 9). Like every loop of the product it
   runs with Full motion only (so never when the system asks for less), and live.js pauses it while it is off screen. */
:root[data-motion="full"] .live-dot { animation: live-pulse var(--live-pulse) ease-in-out infinite; }
:root[data-motion="full"] .live-off .live-dot { animation-play-state: paused; }
@keyframes live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

.live-example { display: inline-flex; align-items: center; min-height: 22px; padding: 0 9px; border-radius: 999px; background: var(--a-tag-bg);
  color: var(--a-tag-ink); font-size: var(--a-t-2xs, 11px); font-weight: 600; white-space: nowrap; }

.live-num { font-variant-numeric: tabular-nums; }

/* the area line: an SVG on a 0-100 grid stretched to the box, the point and the tooltip placed by --pt-x / --pt-y (live.js) */
.live-chart { position: relative; min-height: 130px; cursor: crosshair; touch-action: pan-y; border-radius: 8px; }
.live-chart svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.live-chart-rule { stroke: var(--glow-grid); stroke-width: 1; stroke-dasharray: 3 4; vector-effect: non-scaling-stroke; }
.live-chart-fill stop { stop-color: rgb(var(--acc-rgb, var(--acc-emerald-rgb))); }
.live-chart-line { fill: none; stroke: var(--acc, var(--acc-emerald)); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke; filter: drop-shadow(0 0 6px rgba(var(--acc-rgb, var(--acc-emerald-rgb)), 0.7)); }
.live-chart-x { stroke: rgba(var(--acc-rgb, var(--acc-emerald-rgb)), 0.45); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke;
  opacity: 0; }
.live-pt { position: absolute; left: var(--pt-x, 100%); top: var(--pt-y, 50%); width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
  border: 2px solid var(--glow-face); background: var(--acc, var(--acc-emerald)); box-shadow: 0 0 12px rgba(var(--acc-rgb, var(--acc-emerald-rgb)), 0.9);
  pointer-events: none; }
.live-tip { position: absolute; left: clamp(48px, var(--pt-x, 100%), calc(100% - 48px)); top: max(calc(var(--pt-y, 50%) - 14px), 40px);
  transform: translate(-50%, -100%); padding: 6px 10px; border: 1px solid var(--glow-line); border-radius: 8px;
  background: var(--popover, var(--glow-face)); color: var(--foreground); font-size: var(--a-t-xs, 12px); line-height: 1.35; white-space: nowrap;
  box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.5); pointer-events: none; opacity: 0; }
.live-tip-k { display: block; color: var(--muted-foreground); }
.live-tip-v { display: block; font-weight: 600; font-variant-numeric: tabular-nums; }
.live-chart.is-reading .live-tip, .live-chart.is-reading .live-chart-x { opacity: 1; }
.live-say { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* a score ring: the track, the arc (its length is the score, set by live.js), the number in the middle, the label under it */
.live-ring { display: inline-flex; flex-direction: column; align-items: center; gap: 8px; }
.live-ring-dial { position: relative; width: 56px; height: 56px; }
.live-ring-dial svg { display: block; width: 100%; height: 100%; transform: rotate(-90deg); }
.live-ring-track { fill: none; stroke: var(--glow-grid); stroke-width: 4; }
.live-ring-arc { fill: none; stroke: var(--acc, var(--acc-emerald)); stroke-width: 4; stroke-linecap: round; transform-origin: 25px 25px; }
.live-ring.is-wait .live-ring-arc { opacity: 0; }
.live-ring.is-in .live-ring-arc { animation: live-ring-in var(--live-ring) cubic-bezier(0.4, 0, 0.2, 1) both; }
@keyframes live-ring-in { from { opacity: 0; transform: rotate(-150deg); } to { opacity: 1; transform: rotate(0deg); } }
.live-ring-n { position: absolute; inset: 0; display: grid; place-items: center; color: var(--foreground); font-size: var(--a-t-sm, 14px); font-weight: 600;
  font-variant-numeric: tabular-nums; }
.live-ring-l { color: var(--muted-foreground); font-size: var(--a-t-2xs, 11px); }

/* bars: every bar is the full height and is scaled to its value from the baseline (--v, 0 to 1, set by live.js) */
.live-bars { display: flex; align-items: flex-end; gap: 4px; height: 56px; }
.live-bar { flex: 1; height: 100%; border-radius: 2px 2px 0 0; background: rgba(var(--acc-rgb, var(--acc-emerald-rgb)), 0.3);
  transform: scaleY(var(--v, 0.08)); transform-origin: 50% 100%; transition: transform var(--live-bar) var(--motion-ease-out, ease-out); }
.live-bar.is-now { background: var(--acc, var(--acc-emerald)); box-shadow: 0 0 10px rgba(var(--acc-rgb, var(--acc-emerald-rgb)), 0.8); }

/* ==== still: the system asks for reduced motion, or the page's motion is off (the rule of shared/js/motion.js: the system's setting
   wins over everything). Every duration above is zero, so nothing pulses, turns or grows: each live piece is in its final state at
   once. The card has no light at all: it is quiet and wears its accent on its edge. ==== */
@media (prefers-reduced-motion: reduce) {
  :root { --glow-fade: 0ms; --live-pulse: 0ms; --live-ring: 0ms; --live-bar: 0ms; }
  :is(.glow, .glow-fx)::before, :is(.glow, .glow-fx)::after { display: none; }
  .glow { box-shadow: inset 0 0 0 1px rgba(var(--acc-rgb, var(--acc-emerald-rgb)), var(--glow-still)); }
  .live-ring.is-wait .live-ring-arc { opacity: 1; }
}
:root[data-motion="off"] { --glow-fade: 0ms; --live-pulse: 0ms; --live-ring: 0ms; --live-bar: 0ms; }
:root[data-motion="off"] :is(.glow, .glow-fx)::before, :root[data-motion="off"] :is(.glow, .glow-fx)::after { display: none; }
:root[data-motion="off"] .glow { box-shadow: inset 0 0 0 1px rgba(var(--acc-rgb, var(--acc-emerald-rgb)), var(--glow-still)); }
:root[data-motion="off"] .live-ring.is-wait .live-ring-arc { opacity: 1; }

/* forced colours: the system's own edge, no light. Print: paper has no pointer. */
@media (forced-colors: active) {
  .glow { border: 1px solid CanvasText; box-shadow: none; }
  :is(.glow, .glow-fx)::before, :is(.glow, .glow-fx)::after { display: none; }
  .live-chart-line, .live-ring-arc { stroke: CanvasText; }
  .live-bar, .live-pt { background: CanvasText; forced-color-adjust: none; }
}
@media print {
  :is(.glow, .glow-fx)::before, :is(.glow, .glow-fx)::after { display: none; }
  .live-tip { display: none; }
}
