/* ============================================================
   CloudXOps widget kit
   The case study and article widgets used to be hairline boxes on near black:
   1px rectangles, flat dots, plain bars. This is the same drawing language the
   service scenes use (src/scenes/kit.js), written as CSS so every widget can
   pick it up: graphite chassis with a lit top edge, glass tiles with a tinted
   inner glow, gems with a halo and a specular, energy beams with a soft halo
   and a white core, and inset meters that fill behind a lit head.

   Everything is scoped under .cxo-article and takes its colour from --k, so a
   widget sets --k once (or per element) and the whole vocabulary follows.

   Motion rule: nothing here animates at rest. Beads and pulses only run under
   .is-live / :hover, and the reveal helpers are one shot with a forwards fill.
   ============================================================ */

.cxo-article{
  /* the accent every kit part reads; a widget or an element can override it */
  --k:#a855f7;
  --k-hot:#dcc4ff;      /* tint .62 */
  --k-deep:#3f1f6b;     /* shade .5 */
  --k-rgb:168,85,247;
  --kit-glass:linear-gradient(135deg,rgba(255,255,255,.10),rgba(255,255,255,.02));
  --kit-chassis:linear-gradient(180deg,#23243a,#121322);
  --kit-inset:linear-gradient(180deg,#0a0b15,#1a1b2c);
  --kit-flick:cubic-bezier(.25,.46,.45,.94);
}

/* named tones, so a widget can say .k-cyan on a subtree instead of repeating hexes */
.cxo-article .k-violet{--k:#a855f7;--k-hot:#dcc4ff;--k-deep:#3f1f6b;--k-rgb:168,85,247;}
.cxo-article .k-cyan  {--k:#22d3ee;--k-hot:#bdf1fa;--k-deep:#0d5b69;--k-rgb:34,211,238;}
.cxo-article .k-green {--k:#4ade80;--k-hot:#c4f4d5;--k-deep:#1f6b39;--k-rgb:74,222,128;}
.cxo-article .k-amber {--k:#fbbf24;--k-hot:#fee9b6;--k-deep:#7a5b0d;--k-rgb:251,191,36;}
.cxo-article .k-red   {--k:#f87171;--k-hot:#fcc9c9;--k-deep:#7a2f2f;--k-rgb:248,113,113;}
.cxo-article .k-teal  {--k:#2dd4bf;--k-hot:#bff1ea;--k-deep:#146a60;--k-rgb:45,212,191;}
.cxo-article .k-blue  {--k:#60a5fa;--k-hot:#cfe3fd;--k-deep:#2b4d7d;--k-rgb:96,165,250;}
.cxo-article .k-slate {--k:#6f7090;--k-hot:#b3b4c6;--k-deep:#2a2b40;--k-rgb:111,112,144;}

/* ---------- chassis: the graphite body a machine is built from ---------- */
.cxo-article .k-chassis{
  position:relative;border-radius:14px;
  background:var(--kit-chassis);
  border:1px solid rgba(255,255,255,.11);
  box-shadow:0 4px 14px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.055);
}
/* the sheen down the top third and the lit edge across the very top */
.cxo-article .k-chassis::before{
  content:"";position:absolute;left:0;right:0;top:0;height:38%;border-radius:14px 14px 0 0;
  background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(255,255,255,0));pointer-events:none;
}
.cxo-article .k-chassis::after{
  content:"";position:absolute;left:14px;right:14px;top:-1px;height:1.2px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.42) 50%,transparent);
}
.cxo-article .k-chassis.on{
  border-color:rgba(var(--k-rgb),.6);
  background:
    radial-gradient(140% 90% at 50% 0%,rgba(var(--k-rgb),.16),transparent 66%),
    var(--kit-chassis);
}
.cxo-article .k-chassis.on::after{
  background:linear-gradient(90deg,transparent,var(--k-hot) 50%,transparent);opacity:.9;
}

/* ---------- tile: a glass panel that reads as a screen ---------- */
.cxo-article .k-tile{
  position:relative;border-radius:12px;
  background:var(--kit-glass),#0f1020;
  border:1px solid rgba(255,255,255,.13);
  box-shadow:0 2px 8px rgba(0,0,0,.45);
  transition:border-color .1s var(--kit-flick),background-color .1s var(--kit-flick);
}
.cxo-article .k-tile::after{
  content:"";position:absolute;left:12px;right:12px;top:-1px;height:1.2px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.42) 50%,transparent);
}
.cxo-article .k-tile.on{
  background:
    radial-gradient(120% 76% at 50% 0%,rgba(var(--k-rgb),.20),transparent 70%),
    var(--kit-glass),#0f1020;
  border-color:rgba(var(--k-rgb),.38);
}
.cxo-article .k-tile.on::after{background:linear-gradient(90deg,transparent,var(--k-hot) 50%,transparent);}

/* slab: a small glass strip (a repo row, a log line, a fragment) */
.cxo-article .k-slab{
  border-radius:5px;background:var(--kit-glass);
  border:1px solid rgba(255,255,255,.12);
}
.cxo-article .k-slab.on{
  background:linear-gradient(135deg,rgba(var(--k-rgb),.16),rgba(var(--k-rgb),.05));
  border-color:rgba(var(--k-rgb),.45);
}

/* ---------- gem: halo, dark seat, radial body, bright ring, specular ---------- */
.cxo-article .k-gem{
  position:relative;display:inline-grid;place-items:center;flex:none;
  width:26px;height:26px;border-radius:50%;
  color:#fff;
  background:radial-gradient(circle at 35% 28%,var(--k-hot) 0%,var(--k) 46%,var(--k-deep) 100%);
  box-shadow:0 2px 0 1px rgba(0,0,0,.38), inset 0 0 0 1px rgba(255,255,255,.34);
  transition:background .35s ease, box-shadow .1s var(--kit-flick);
}
.cxo-article .k-gem::before{           /* the halo */
  content:"";position:absolute;inset:-11px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(var(--k-rgb),.36) 0%,rgba(var(--k-rgb),.12) 40%,rgba(var(--k-rgb),0) 70%);
  transition:opacity .35s ease;
}
.cxo-article .k-gem::after{            /* the specular */
  content:"";position:absolute;left:22%;top:16%;width:34%;height:20%;border-radius:50%;
  background:#fff;opacity:.4;transform:rotate(-28deg);pointer-events:none;
}
.cxo-article .k-gem > svg,.cxo-article .k-gem > i{width:56%;height:56%;position:relative;z-index:1;}
/* an unlit gem is the same object with the light off, never a different shape */
.cxo-article .k-gem.off{
  background:radial-gradient(circle at 35% 28%,#6f7090 0%,#2a2b40 50%,#15162a 100%);
  box-shadow:0 2px 0 1px rgba(0,0,0,.38), inset 0 0 0 1px rgba(255,255,255,.13);
}
.cxo-article .k-gem.off::before{opacity:0;}
.cxo-article .k-gem.off::after{opacity:.14;}
.cxo-article .k-gem.sm{width:18px;height:18px;}
.cxo-article .k-gem.sm::before{inset:-8px;}
.cxo-article .k-gem.lg{width:34px;height:34px;}

/* LED: the same gem language at dot scale, for status rows and drive bays */
.cxo-article .k-led{
  position:relative;display:inline-block;width:8px;height:8px;border-radius:50%;flex:none;
  background:radial-gradient(circle at 40% 35%,#fff 0%,var(--k-hot) 45%,var(--k) 100%);
  transition:background .3s ease;
}
.cxo-article .k-led::before{
  content:"";position:absolute;inset:-6px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(var(--k-rgb),.5) 0%,rgba(var(--k-rgb),.16) 42%,transparent 70%);
  transition:opacity .3s ease;
}
.cxo-article .k-led.off{background:radial-gradient(circle at 40% 35%,#7b7c9a 0%,#3a3b52 100%);}
.cxo-article .k-led.off::before{opacity:0;}

/* ---------- beam: soft halo, gradient core, white inner line ---------- */
.cxo-article .k-beam{
  position:relative;flex:none;
  background:linear-gradient(90deg,rgba(var(--k-rgb),.55),var(--k) 55%,var(--k-hot));
  border-radius:2px;
}
.cxo-article .k-beam::before{          /* the halo around the core */
  content:"";position:absolute;left:0;right:0;top:50%;height:14px;transform:translateY(-50%);
  border-radius:7px;pointer-events:none;
  background:linear-gradient(180deg,rgba(var(--k-rgb),0),rgba(var(--k-rgb),.28) 50%,rgba(var(--k-rgb),0));
}
.cxo-article .k-beam::after{           /* the white line inside it */
  content:"";position:absolute;left:2px;right:2px;top:50%;height:1px;transform:translateY(-50%);
  background:rgba(255,255,255,.34);pointer-events:none;
}
.cxo-article .k-beam.v{background:linear-gradient(180deg,rgba(var(--k-rgb),.55),var(--k) 55%,var(--k-hot));}
.cxo-article .k-beam.v::before{left:50%;right:auto;top:0;bottom:0;height:auto;width:14px;
  transform:translateX(-50%);border-radius:7px;
  background:linear-gradient(90deg,rgba(var(--k-rgb),0),rgba(var(--k-rgb),.28) 50%,rgba(var(--k-rgb),0));}
.cxo-article .k-beam.v::after{left:50%;right:auto;top:2px;bottom:2px;height:auto;width:1px;
  transform:translateX(-50%);}
/* A dead run: the same path with the light off. Drawn as a background rather than a
   border so an inactive beam occupies exactly the same box as a live one and a state
   change never nudges the layout. */
.cxo-article .k-beam.off{
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.16) 0 4px,transparent 4px 9px);}
.cxo-article .k-beam.v.off{
  background:repeating-linear-gradient(180deg,rgba(255,255,255,.16) 0 4px,transparent 4px 9px);}
.cxo-article .k-beam.off::before,.cxo-article .k-beam.off::after{display:none;}
.cxo-article .k-beam.off > .head{display:none;}

/* The travelling head, only while the run is live. The head is a rail as long as its
   beam and the bead itself is drawn on ::before, so the travel is a percentage translate
   of the rail (which is the beam's own length) instead of an animated left/top. Moving a
   layout property here relaid and repainted the beam and its 12px glow on every frame,
   forever; a transform runs on the compositor. */
.cxo-article .k-beam > .head{
  position:absolute;top:50%;left:0;width:100%;height:7px;margin-top:-3.5px;
  opacity:0;pointer-events:none;
}
.cxo-article .k-beam > .head::before{
  content:"";position:absolute;left:-3.5px;top:0;width:7px;height:7px;border-radius:50%;
  background:radial-gradient(circle at 40% 35%,#fff 0%,var(--k-hot) 45%,var(--k) 100%);
  box-shadow:0 0 12px 4px rgba(var(--k-rgb),.42);
}
.cxo-article .k-beam.v > .head{top:0;left:50%;width:7px;height:100%;margin:0 0 0 -3.5px;}
.cxo-article .k-beam.v > .head::before{left:0;top:-3.5px;}
.cxo-article .k-beam.is-live > .head{opacity:1;animation:kBead 1.4s cubic-bezier(.45,0,.55,1) infinite;}
.cxo-article .k-beam.v.is-live > .head{animation-name:kBeadV;}
@keyframes kBead{from{transform:translateX(2%)}to{transform:translateX(98%)}}
@keyframes kBeadV{from{transform:translateY(2%)}to{transform:translateY(98%)}}

/* ---------- meter: inset track, glow band, gradient core, gloss, lit head ---------- */
.cxo-article .k-meter{
  position:relative;height:8px;border-radius:4px;overflow:visible;
  background:var(--kit-inset);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);
}
.cxo-article .k-meter > .fill{
  position:absolute;left:0;top:0;bottom:0;width:0;border-radius:4px;
  background:linear-gradient(90deg,var(--k-deep),var(--k) 55%,var(--k-hot));
  transition:width .95s cubic-bezier(.22,.61,.36,1);
}
.cxo-article .k-meter > .fill::before{   /* the glow band bleeding out of the track */
  content:"";position:absolute;left:-2px;right:-2px;top:-6px;bottom:-6px;border-radius:10px;
  background:linear-gradient(180deg,rgba(var(--k-rgb),0),rgba(var(--k-rgb),.3) 50%,rgba(var(--k-rgb),0));
  pointer-events:none;
}
.cxo-article .k-meter > .fill::after{    /* the gloss along the top of the core */
  content:"";position:absolute;left:3px;right:3px;top:1.5px;height:2px;border-radius:1px;
  background:rgba(255,255,255,.3);pointer-events:none;
}
.cxo-article .k-meter > .fill > .head{   /* the lit head riding the end of the fill */
  position:absolute;right:-3px;top:50%;width:7px;height:7px;margin-top:-3.5px;border-radius:50%;
  background:radial-gradient(circle at 40% 35%,#fff 0%,var(--k-hot) 45%,var(--k) 100%);
  box-shadow:0 0 12px 4px rgba(var(--k-rgb),.4);
}
.cxo-article .k-meter.tall{height:12px;border-radius:6px;}
.cxo-article .k-meter.tall > .fill{border-radius:6px;}

/* vertical meter (a gauge column) */
.cxo-article .k-meter.vert{height:auto;width:12px;border-radius:6px;}
.cxo-article .k-meter.vert > .fill{
  top:auto;bottom:0;left:0;right:0;width:auto;height:0;border-radius:6px;
  background:linear-gradient(0deg,var(--k-deep),var(--k) 55%,var(--k-hot));
  transition:height .95s cubic-bezier(.22,.61,.36,1);
}
.cxo-article .k-meter.vert > .fill::after{left:1.5px;right:1.5px;top:3px;height:auto;bottom:3px;width:2px;}
.cxo-article .k-meter.vert > .fill > .head{right:50%;top:-3px;margin:0 -3.5px 0 0;}

/* ---------- sparkline: a glow twin under the core stroke ---------- */
.cxo-article .k-spark{overflow:visible;}
.cxo-article .k-spark .halo{
  fill:none;stroke:var(--k);stroke-opacity:.22;stroke-width:7;
  stroke-linecap:round;stroke-linejoin:round;
}
.cxo-article .k-spark .core{
  fill:none;stroke:var(--k);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
.cxo-article .k-spark .inner{
  fill:none;stroke:#fff;stroke-opacity:.32;stroke-width:.8;
  stroke-linecap:round;stroke-linejoin:round;
}
.cxo-article .k-spark .area{fill:var(--k);fill-opacity:.10;stroke:none;}
.cxo-article .k-spark .grid{stroke:rgba(255,255,255,.055);stroke-width:1;}
.cxo-article .k-spark .tip{fill:var(--k-hot);stroke:#fff;stroke-width:1.1;}

/* ---------- console: a screen in a bezel, not a grey box ---------- */
.cxo-article .k-console{
  position:relative;border-radius:12px;padding:12px 14px;
  background:
    linear-gradient(180deg,rgba(255,255,255,.03),rgba(255,255,255,0) 32%),
    var(--kit-inset);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07), inset 0 12px 24px -18px rgba(var(--k-rgb),.55);
  font-family:var(--font-mono);font-size:12.5px;line-height:1.75;color:var(--dim);
}
.cxo-article .k-console::after{
  content:"";position:absolute;left:14px;right:14px;top:-1px;height:1.2px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(var(--k-rgb),.55) 50%,transparent);
}
/* A console that scrolls keeps whole lines at its top edge: the log is auto scrolled to
   the bottom, and a line sliced through the glyphs reads as a rendering fault. */
.cxo-article .k-console{scroll-snap-type:y proximity;}
.cxo-article .k-console > *{scroll-snap-align:end;}

/* ---------- one shot reveal helpers ---------- */
/* Elements marked .k-in start hidden and land when the widget adds .k-go to a
   container. Forwards fill, so once landed nothing is left running. */
.cxo-article .k-go .k-in{animation:kIn .44s cubic-bezier(.22,.61,.36,1) calc(var(--i,0) * 58ms) both;}
@keyframes kIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.cxo-article .k-go .k-pop{animation:kPop .46s cubic-bezier(.34,1.4,.5,1) calc(var(--i,0) * 58ms) both;}
@keyframes kPop{from{opacity:0;transform:scale(.72)}to{opacity:1;transform:none}}

/* a gem that is actively working breathes; only while the widget says so */
.cxo-article .k-gem.is-live::before{animation:kHalo 1.5s ease-in-out infinite;}
@keyframes kHalo{0%,100%{opacity:.55;}50%{opacity:1;}}
/* an expanding ring off a live gem, for a sensor or a probe that is sampling */
.cxo-article .k-ring{
  position:absolute;inset:0;border-radius:50%;pointer-events:none;
  border:1.6px solid var(--k);opacity:0;
}
.cxo-article .k-gem.is-live > .k-ring{animation:kRing 1.5s ease-out infinite;}
@keyframes kRing{0%{transform:scale(1);opacity:.6}100%{transform:scale(2.5);opacity:0}}

@media (prefers-reduced-motion: reduce){
  .cxo-article .k-beam.is-live > .head,
  .cxo-article .k-gem.is-live::before,
  .cxo-article .k-gem.is-live > .k-ring,
  .cxo-article .k-go .k-in,.cxo-article .k-go .k-pop{animation:none;}
  .cxo-article .k-beam.is-live > .head{opacity:1;transform:translateX(50%);}
  .cxo-article .k-beam.v.is-live > .head{transform:translateY(50%);}
  .cxo-article .k-meter > .fill{transition:none;}
}
