/* ==========================================================================
   Dashboard bento 1.0 — a hero whose figures are the illustration
   --------------------------------------------------------------------------
   Plain CSS. No framework, no build step, no external request: the two font
   files and every drawing live in this folder or in this file.

   Six cards report on a system — nodes online, latency, uptime, coverage. The
   drawings that carry them (bar chart, radar sweep, hatched gauges) are drawn
   with gradients and borders rather than shipped as images, so they stay
   sharp at any size and carry no third-party asset.

   PROPORTIONS
   Every metric derives from --tb-font-size, the size of the running text.
   The ratios below were measured on the original, box by box:

     running text     1                (the reference: 16 px)
     headline         3.75 em          and so is every hero figure
     card padding     2 em
     card radius      0.5 em
     grid gap         0.5 em
     label            1 em, uppercase, 1.25 line-height
     badge            0.875 em, 0.375 em / 0.625 em of padding
     bar chart        10.875 em wide, 4 em tall, 0.125 em between bars
     uptime columns   6.25 em tall, twelve of them
     gauge            0.5 em tall, hatched every 0.25 em
     radar            square, as wide as the card allows

   Changing --tb-font-size rescales the whole block, drawings included.
   The four responsive steps below reproduce the original's own steps; they
   are container queries, so the block adapts to the space it is given rather
   than to the size of the window.

   Order of this file:
     1. Fonts
     2. Design tokens
     3. Block, background grid
     4. Headline, lead, buttons
     5. Bento grids and card shell
     6. Shared card parts: label, badge, figure, note, rule
     7. Card 1 — bar chart
     8. Card 3 — pulsing dot
     9. Card 4 — radar
    10. Card 5 — uptime columns
    11. Card 6 — hatched gauges
    12. Entrance motion (driven by the script)
    13. Responsive steps
    14. Fallbacks: reduced motion, forced colours

   Naming follows BEM: .dashboard-bento, .dashboard-bento__part,
   .dashboard-bento--variant.
   ========================================================================== */

/* ==========================================================================
   1. Fonts
   Subset of IBM Plex Sans (SIL Open Font License 1.1), latin only.
   ========================================================================== */

@font-face {
  font-family: "IBM Plex Sans";
  src: url("IBMPlexSans-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("IBMPlexSans-500-latin.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   2. Design tokens
   ========================================================================== */

.dashboard-bento {
  /* Scale. One number rescales the block. */
  --tb-font-size: 1rem;

  /* Palette. */
  --tb-surface: #0f0f0f; /* section and five of the six cards */
  --tb-surface-raised: #191919; /* the first card sits one step lighter */
  --tb-line: #414141; /* borders, hollow bars, rules */
  --tb-text: #b4b4b4;
  --tb-title: #fff;
  --tb-ok: #1ed760; /* rising figures, "online" */
  --tb-alert: #ff5b48; /* falling figures */
  --tb-sweep: #262626; /* the radar beam */
  --tb-backdrop: #181818; /* the grid behind everything */

  /* Data. The numbers the drawings show — change them here, nowhere else.
     Text figures live in the markup, since a screen reader has to read them. */
  --tb-chart-1: 62%;
  --tb-chart-2: 48%;
  --tb-chart-3: 70%;
  --tb-chart-4: 100%;
  --tb-chart-5: 48%;
  --tb-ratio: 73%; /* the progress bar under the radar */
  --tb-gauge-1: 81%;
  --tb-gauge-2: 72%;
  --tb-gauge-3: 62%;

  /* Spacing. Absolute on purpose: a custom property written in em would be
     resolved by whoever reads it, and a card padding read from a 60 px figure
     would come out four times too wide. */
  --tb-gap: calc(0.5 * var(--tb-font-size)); /* between cards */
  --tb-gap-rows: calc(0.625 * var(--tb-font-size)); /* between the two grids */
  --tb-pad-card: calc(2 * var(--tb-font-size));
  --tb-pad-card-bottom: calc(2.5 * var(--tb-font-size)); /* first card only */
  --tb-pad-side: calc(1.5 * var(--tb-font-size)); /* container gutter */
  --tb-pad-top: calc(3 * var(--tb-font-size)); /* above the headline */
  --tb-row-gap-x: calc(1.5 * var(--tb-font-size)); /* inside a card row */
  --tb-row-gap-y: calc(1 * var(--tb-font-size));
  --tb-stack: calc(2.5 * var(--tb-font-size)); /* card 6, label to gauges */
  --tb-content: calc(1.25 * var(--tb-font-size)); /* vertical step: rules, gauges */
  --tb-pad-button-y: calc(0.75 * var(--tb-font-size));
  --tb-region-gap: calc(2 * var(--tb-font-size)); /* region name to figure */
  --tb-max: calc(80.375 * var(--tb-font-size)); /* container */
  --tb-max-title: calc(31.25 * var(--tb-font-size));
  --tb-max-lead: calc(28.75 * var(--tb-font-size));

  /* Type. */
  --tb-figure: calc(3.75 * var(--tb-font-size)); /* headline and hero figures */
  --tb-figure-small: calc(1.125 * var(--tb-font-size));
  --tb-label: calc(1 * var(--tb-font-size));
  --tb-badge: calc(0.875 * var(--tb-font-size));
  --tb-note: calc(0.75 * var(--tb-font-size));
  --tb-icon: calc(1 * var(--tb-font-size));
  --tb-leading: 1.25;
  --tb-leading-lead: 1.55;
  --tb-tracking: -0.03em;

  /* Shapes. */
  --tb-radius: calc(0.5 * var(--tb-font-size));
  --tb-radius-small: calc(0.25 * var(--tb-font-size));
  --tb-radius-tiny: calc(0.125 * var(--tb-font-size));
  --tb-hairline: calc(0.0625 * var(--tb-font-size));

  /* Durations. Read off the original's interaction data, not stopwatched. */
  --tb-in-duration: 400ms; /* fade of one block */
  --tb-in-step: 100ms; /* between two blocks */
  --tb-in-delay: 300ms; /* before the first one */
  --tb-count-duration: 2000ms; /* the figures counting up */
  --tb-bar-duration: 600ms;
  --tb-column-duration: 400ms;
  --tb-radar-duration: 10s; /* five seconds turning, five at rest */
  --tb-pulse-duration: 5s;
  --tb-hover-duration: 300ms;
  --tb-hover-step: 100ms;

  /* Curves, named as the original names them. */
  --tb-ease: cubic-bezier(0.25, 0.1, 0.25, 1);
  --tb-ease-out: cubic-bezier(0, 0, 0.58, 1);
  --tb-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --tb-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
}

/* The probe the script reads its durations from. It has a box — a probe set
   to display: none would report nothing — but takes no room and is invisible. */
.dashboard-bento__probe {
  position: absolute;
  width: 1px;
  height: 1px;
  visibility: hidden;
  pointer-events: none;
  transition-property: opacity;
  transition-duration: var(--tb-count-duration);
  transition-delay: var(--tb-in-step);
}

/* ==========================================================================
   3. Block, background grid
   ========================================================================== */

.dashboard-bento,
.dashboard-bento *,
.dashboard-bento *::before,
.dashboard-bento *::after {
  /* The block states its own box model and assumes no reset. */
  box-sizing: border-box;
}

.dashboard-bento {
  position: relative;
  container-type: inline-size;
  container-name: dashboard-bento;
  overflow: hidden; /* the backdrop overshoots the top edge */
  background-color: var(--tb-surface);
  color: var(--tb-text);
  font-family: "IBM Plex Sans", Arial, sans-serif;
  font-size: var(--tb-font-size);
  font-weight: 400;
  line-height: var(--tb-leading-lead);
  letter-spacing: var(--tb-tracking);
  text-align: start;
}

/* A square grid, fading out towards the edges of an ellipse. The original
   ships it as a 2880 px image; here it is two gradients and a mask, which
   costs no request and stays sharp when the block is wider.

   The tile carries its line down the middle so that background-position:
   center puts a line exactly on the centre of the block, as in the original.
   4.1667% of the width is 1/24th: the image holds twenty-four columns. */
.dashboard-bento__backdrop {
  position: absolute;
  inset: -12% 0 auto;
  z-index: 0;
  width: 100%;
  max-width: calc(90 * var(--tb-font-size));
  margin-inline: auto;
  aspect-ratio: 2880 / 2639;
  pointer-events: none;
  background-image:
    linear-gradient(
      to right,
      transparent calc(50% - 0.5px),
      var(--tb-backdrop) calc(50% - 0.5px) calc(50% + 0.5px),
      transparent calc(50% + 0.5px)
    ),
    linear-gradient(
      to bottom,
      transparent calc(50% - 0.5px),
      var(--tb-backdrop) calc(50% - 0.5px) calc(50% + 0.5px),
      transparent calc(50% + 0.5px)
    );
  background-position: center;
  background-size: 4.1667% 4.5473%;
  /* Measured on the original: alpha 1 at the centre, 0.57 halfway, 0 on the
     ellipse. Four stops land within 0.02 of the measured profile. */
  -webkit-mask-image: radial-gradient(
    closest-side ellipse at center,
    #000 0%,
    #000d 25%,
    #0009 50%,
    #0004 75%,
    #0000 100%
  );
  mask-image: radial-gradient(
    closest-side ellipse at center,
    #000 0%,
    #000d 25%,
    #0009 50%,
    #0004 75%,
    #0000 100%
  );
}

/* The steps at the foot of this file redefine the variables HERE and not on
   the block: a container never styles itself — a container query only reaches
   its descendants. That is also why the top padding hangs on this element. */
.dashboard-bento__container {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--tb-max);
  margin-inline: auto;
  padding-top: var(--tb-pad-top);
  padding-inline: var(--tb-pad-side);

  /* The lone figure of the latency card steps down sooner than the others.
     Declared here and not on the block: a custom property is resolved where
     it is declared, so one written on the block would keep the wide value. */
  --tb-figure-lead: var(--tb-figure);
}

/* ==========================================================================
   4. Headline, lead, buttons
   ========================================================================== */

.dashboard-bento__intro {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--tb-gap);
  margin-bottom: var(--tb-pad-top);
}

.dashboard-bento__title {
  max-width: var(--tb-max-title);
  margin: 0;
  color: var(--tb-title);
  font-size: var(--tb-figure);
  font-weight: 500;
  line-height: var(--tb-leading);
  letter-spacing: var(--tb-tracking);
}

.dashboard-bento__lead {
  max-width: var(--tb-max-lead);
}

.dashboard-bento__lead p {
  margin: 0;
}

.dashboard-bento__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tb-row-gap-y);
  margin-top: var(--tb-row-gap-y);
}

.dashboard-bento__button {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--tb-pad-button-y) var(--tb-pad-side);
  overflow: hidden;
  border: var(--tb-hairline) solid var(--tb-title);
  border-radius: var(--tb-radius-small);
  font: inherit;
  font-weight: 500;
  line-height: var(--tb-leading-lead);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.dashboard-bento__button--primary {
  background-color: var(--tb-title);
  color: var(--tb-surface);
}

.dashboard-bento__button--secondary {
  background-color: transparent;
  color: var(--tb-title);
  font-weight: 400;
}

.dashboard-bento__button:focus-visible {
  outline: calc(0.125 * var(--tb-font-size)) solid var(--tb-ok);
  outline-offset: calc(0.125 * var(--tb-font-size));
}

/* Hover: five slats sweep across the button, out from the middle. Odd slats
   grow from the bottom, even ones from the top, which is what gives the
   closing-comb look. The label changes colour halfway through. */
.dashboard-bento__comb {
  position: absolute;
  inset: 0;
  z-index: -1;
  display: flex;
  pointer-events: none;
}

.dashboard-bento__comb span {
  flex: 1 1 20%;
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform var(--tb-hover-duration) var(--tb-ease);
}

.dashboard-bento__comb span:nth-child(even) {
  transform-origin: 50% 0;
}

.dashboard-bento__button--primary .dashboard-bento__comb span {
  background-color: var(--tb-surface);
}

.dashboard-bento__button--secondary .dashboard-bento__comb span {
  background-color: var(--tb-title);
}

/* Middle first, then its neighbours, then the ends. */
.dashboard-bento__comb span:nth-child(3) {
  transition-delay: 0ms;
}

.dashboard-bento__comb span:nth-child(2),
.dashboard-bento__comb span:nth-child(4) {
  transition-delay: var(--tb-hover-step);
}

.dashboard-bento__comb span:nth-child(1),
.dashboard-bento__comb span:nth-child(5) {
  transition-delay: calc(2 * var(--tb-hover-step));
}

.dashboard-bento__button:hover .dashboard-bento__comb span,
.dashboard-bento__button:focus-visible .dashboard-bento__comb span {
  transform: scaleY(1);
}

.dashboard-bento__button {
  transition: color var(--tb-hover-duration) var(--tb-ease) var(--tb-hover-step);
}

.dashboard-bento__button--primary:hover,
.dashboard-bento__button--primary:focus-visible {
  color: var(--tb-title);
}

.dashboard-bento__button--secondary:hover,
.dashboard-bento__button--secondary:focus-visible {
  color: var(--tb-surface);
}

/* ==========================================================================
   5. Bento grids and card shell
   ========================================================================== */

.dashboard-bento__grid {
  display: grid;
  gap: var(--tb-gap);
}

/* minmax(0, …) and not 1fr: a grid column's automatic minimum is its content,
   which would push the track wider than its share. */
.dashboard-bento__grid--top {
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr);
  margin-bottom: var(--tb-gap-rows);
}

.dashboard-bento__grid--bottom {
  grid-template-columns: minmax(0, 0.56fr) minmax(0, 0.7fr) minmax(0, 1fr);
}

.dashboard-bento__card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--tb-pad-card);
  border: var(--tb-hairline) solid var(--tb-line);
  border-radius: var(--tb-radius);
  background-color: var(--tb-surface);
}

/* The first card is one shade lighter, taller-spaced, and sits on more room
   below its figure. */
.dashboard-bento__card--raised {
  padding-bottom: var(--tb-pad-card-bottom);
  gap: calc(5.375 * var(--tb-font-size));
  background-color: var(--tb-surface-raised);
}

.dashboard-bento__card--centred {
  align-items: center;
  justify-content: center;
  text-align: center;
}

.dashboard-bento__card--stacked {
  gap: var(--tb-stack);
}

/* ==========================================================================
   6. Shared card parts
   ========================================================================== */

.dashboard-bento__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--tb-row-gap-y) var(--tb-row-gap-x);
  color: var(--tb-title);
}

.dashboard-bento__row--bottom {
  align-items: flex-end;
}

.dashboard-bento__row--top {
  align-items: flex-start;
}

.dashboard-bento__row--centre {
  justify-content: center;
}

.dashboard-bento__label {
  display: flex;
  align-items: center;
  gap: calc(0.5 * var(--tb-font-size));
  margin: 0;
  min-width: 0;
  font-size: var(--tb-label);
  /* A h2 arrives in bold; this label is not. */
  font-weight: 400;
  /* In em, and declared here on purpose: inherited, the tracking would keep
     the pixel value computed on the parent — 0.48 px instead of 0.42. */
  letter-spacing: var(--tb-tracking);
  overflow-wrap: anywhere;
  line-height: var(--tb-leading);
  text-transform: uppercase;
}

/* Width only: the icons do not share one aspect ratio, and forcing a square
   would squash the ones drawn on a 13 by 16 grid. */
.dashboard-bento__icon {
  flex: none;
  width: var(--tb-icon);
  height: auto;
}

.dashboard-bento__caption {
  margin: 0;
  color: var(--tb-title);
  /* Not --tb-label: the original only shrinks the uppercase labels. */
  font-size: calc(1 * var(--tb-font-size));
  line-height: var(--tb-leading);
  letter-spacing: var(--tb-tracking);
}

.dashboard-bento__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: calc(0.375 * var(--tb-font-size));
  margin: 0;
  padding: calc(0.375 * var(--tb-font-size)) calc(0.625 * var(--tb-font-size));
  border-radius: var(--tb-radius-small);
  font-size: var(--tb-badge);
  line-height: var(--tb-leading);
  text-transform: uppercase;
  white-space: nowrap;
}

.dashboard-bento__badge--ok {
  /* 10 % of the accent over the card: one source of truth for the hue. */
  background-color: color-mix(in srgb, var(--tb-ok) 10%, transparent);
  color: var(--tb-ok);
}

.dashboard-bento__badge--alert {
  background-color: color-mix(in srgb, var(--tb-alert) 10%, transparent);
  color: var(--tb-alert);
}

.dashboard-bento__badge-arrow {
  width: calc(0.5 * var(--tb-font-size));
  height: calc(0.5 * var(--tb-font-size));
}

.dashboard-bento__dot {
  width: calc(0.375 * var(--tb-font-size));
  height: calc(0.375 * var(--tb-font-size));
  border-radius: 50%;
  background-color: currentcolor;
}

.dashboard-bento__figure {
  margin: 0;
  color: var(--tb-title);
  font-size: var(--tb-figure);
  font-weight: 500;
  line-height: var(--tb-leading);
  letter-spacing: var(--tb-tracking);
}

.dashboard-bento__figure--small {
  font-size: var(--tb-figure-small);
}

.dashboard-bento__note {
  margin: 0;
  color: var(--tb-text);
  font-size: var(--tb-note);
  font-weight: 500;
  line-height: var(--tb-leading);
}

.dashboard-bento__note--bright {
  color: var(--tb-title);
}

/* A note set against the baseline of a figure sits a little above it. */
.dashboard-bento__note--lifted {
  margin-bottom: calc(0.625 * var(--tb-font-size));
}

.dashboard-bento__figure--tight {
  margin-bottom: calc(0.5 * var(--tb-font-size));
  font-size: var(--tb-figure-lead);
}

.dashboard-bento__rule {
  height: var(--tb-hairline);
  margin-block: calc(0.625 * var(--tb-font-size));
  background-color: var(--tb-line);
}

.dashboard-bento__rule--wide {
  align-self: stretch;
  margin-top: var(--tb-pad-card);
  margin-bottom: var(--tb-content);
}

/* A badge that sits next to a figure hangs a little lower than its baseline.
   It wraps under it when the card gets too narrow to hold both: the original
   lets it overflow instead, between 992 and 1060 px and under 360. */
.dashboard-bento__inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(0.5 * var(--tb-font-size));
}

/* Only one of the two badges hangs below its figure — the falling one. The
   original gives it a top margin and leaves the rising one flush; at narrow
   widths that margin is what sets the height of the line. */
.dashboard-bento__badge--offset {
  margin-top: var(--tb-row-gap-y);
}

/* ==========================================================================
   7. Card 1 — bar chart
   ========================================================================== */

.dashboard-bento__chart {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: end;
  gap: calc(0.125 * var(--tb-font-size));
  width: 100%;
  max-width: calc(10.875 * var(--tb-font-size));
  min-height: calc(4 * var(--tb-font-size));
}

.dashboard-bento__bar {
  overflow: hidden;
  border-radius: var(--tb-radius-tiny);
  background-color: var(--tb-line);
}

.dashboard-bento__bar:nth-child(1) { height: var(--tb-chart-1); }
.dashboard-bento__bar:nth-child(2) { height: var(--tb-chart-2); }
.dashboard-bento__bar:nth-child(3) { height: var(--tb-chart-3); }
.dashboard-bento__bar:nth-child(4) { height: var(--tb-chart-4); }
.dashboard-bento__bar:nth-child(5) { height: var(--tb-chart-5); }

/* Each bar wears a bright cap; the tallest one is bright all through. */
.dashboard-bento__bar::before {
  display: block;
  height: calc(0.125 * var(--tb-font-size));
  background-color: var(--tb-title);
  content: "";
}

.dashboard-bento__bar--full::before {
  height: 100%;
}

/* ==========================================================================
   8. Card 3 — pulsing dot
   ========================================================================== */

.dashboard-bento__beacon {
  position: relative;
  z-index: 1;
  display: block;
  width: calc(0.625 * var(--tb-font-size));
  height: calc(0.625 * var(--tb-font-size));
  border-radius: 50%;
  background-color: var(--tb-title);
}

.dashboard-bento__beacon--spaced {
  margin-bottom: var(--tb-row-gap-y);
}

/* Two haloes: a blurred one that swells, and a ring that swells further and
   fades. Both come back to rest, wait, and start over. */
.dashboard-bento__beacon::before,
.dashboard-bento__beacon::after {
  position: absolute;
  z-index: -1;
  border-radius: 50%;
  content: "";
  inset: 0;
}

.dashboard-bento__beacon::before {
  background-color: var(--tb-title);
  opacity: 0.5;
  filter: blur(3px);
  animation: tb-halo var(--tb-pulse-duration) var(--tb-ease) infinite;
}

.dashboard-bento__beacon::after {
  border: var(--tb-hairline) solid var(--tb-title);
  opacity: 0.5;
  animation: tb-ring var(--tb-pulse-duration) var(--tb-ease) infinite;
}

@keyframes tb-halo {
  0% { transform: scale(1); }
  20% { transform: scale(1.5); }
  60%, 100% { transform: scale(1); }
}

@keyframes tb-ring {
  0% { transform: scale(1); opacity: 0.5; }
  20% { transform: scale(2.5); opacity: 0; }
  20.01%, 100% { transform: scale(1); opacity: 0.5; }
}

/* ==========================================================================
   9. Card 4 — radar
   --------------------------------------------------------------------------
   Square, as wide as the card allows. Its own container so that the ring
   thickness can follow its width: the original's rings are 4 px on a 704 px
   drawing, that is 0.5682 % of the side, whatever the card measures.
   ========================================================================== */

.dashboard-bento__radar {
  position: relative;
  container-type: inline-size;
  width: 100%;
  aspect-ratio: 1;
  isolation: isolate;
}

.dashboard-bento__radar-ring {
  position: absolute;
  border: 0.5682cqw solid var(--tb-line);
  border-radius: 50%;
}

/* r = 350 on a 704 side: the outer ring touches the edges, half its stroke
   hanging inside. Inset is measured to the middle of the stroke. */
.dashboard-bento__radar-ring--outer {
  inset: 0;
}

/* r = 240 of 352: the inner ring sits at 68.18 % of the outer radius. */
.dashboard-bento__radar-ring--inner {
  inset: 15.909%;
}

.dashboard-bento__radar-cross {
  position: absolute;
  background-color: var(--tb-line);
}

.dashboard-bento__radar-cross--h {
  top: calc(50% - 0.2841cqw);
  right: 0;
  left: 0;
  height: 0.5682cqw;
}

.dashboard-bento__radar-cross--v {
  top: 0;
  bottom: 0;
  left: calc(50% - 0.2841cqw);
  width: 0.5682cqw;
}

/* The beam: a 45° wedge, opaque at the centre and gone at the rim. The mask
   cuts the wedge, the radial gradient fades it. Measured on the original:
   alpha 0.95 at r = 10, 0.02 at r = 350, near enough a straight line. */
.dashboard-bento__radar-sweep {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(
    closest-side circle at center,
    color-mix(in srgb, var(--tb-sweep) 95%, transparent),
    color-mix(in srgb, var(--tb-sweep) 2%, transparent)
  );
  -webkit-mask-image: conic-gradient(from 270deg, #000 0deg 44.7deg, #0000 45.3deg);
  mask-image: conic-gradient(from 270deg, #000 0deg 44.7deg, #0000 45.3deg);
  animation: tb-radar var(--tb-radar-duration) linear infinite;
}

/* Five seconds of a slowing turn, five seconds at rest, then again. */
@keyframes tb-radar {
  0% { transform: rotate(0deg); }
  50%, 100% { transform: rotate(360deg); }
}

.dashboard-bento__radar-sweep {
  animation-timing-function: var(--tb-out-quad);
}

.dashboard-bento__radar-blip {
  position: absolute;
  z-index: 1;
}

/* Positions read off the original, in per cent of the radar. */
.dashboard-bento__radar-blip--1 { top: 18%; right: 40%; }
.dashboard-bento__radar-blip--2 { top: 48%; left: 10%; }
.dashboard-bento__radar-blip--3 { right: 27%; bottom: 12%; }

/* Each blip pulses on its own beat, so the three never breathe together. */
.dashboard-bento__radar-blip--2 .dashboard-bento__beacon::before,
.dashboard-bento__radar-blip--2 .dashboard-bento__beacon::after {
  animation-delay: -1.6s;
}

.dashboard-bento__radar-blip--3 .dashboard-bento__beacon::before,
.dashboard-bento__radar-blip--3 .dashboard-bento__beacon::after {
  animation-delay: -3.2s;
}

.dashboard-bento__radar-value {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  color: var(--tb-title);
  font-size: var(--tb-figure);
  font-weight: 500;
  line-height: var(--tb-leading);
  letter-spacing: var(--tb-tracking);
}

.dashboard-bento__gutter {
  margin-bottom: var(--tb-pad-side);
}

/* The plain progress bar under the radar. */
.dashboard-bento__meter {
  overflow: hidden;
  height: calc(0.5 * var(--tb-font-size));
  margin-top: calc(0.625 * var(--tb-font-size));
  border-radius: var(--tb-radius-tiny);
  background-color: var(--tb-line);
}

.dashboard-bento__meter::before {
  display: block;
  width: var(--tb-ratio);
  height: 100%;
  border-radius: var(--tb-radius-tiny);
  background-color: var(--tb-title);
  content: "";
}

/* ==========================================================================
   10. Card 5 — uptime columns
   ========================================================================== */

.dashboard-bento__columns {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: calc(0.125 * var(--tb-font-size));
  overflow: hidden;
  height: calc(6.25 * var(--tb-font-size));
  margin-top: var(--tb-row-gap-y);
  border-radius: var(--tb-radius-small);
}

.dashboard-bento__column {
  overflow: hidden;
  background-color: var(--tb-line);
  transform-origin: 50% 100%;
}

/* A filled column is white; the last one stays hollow — eleven of twelve. */
.dashboard-bento__column-fill {
  display: block;
  width: 100%;
  height: 100%;
  background-color: var(--tb-title);
  transform-origin: 0 50%;
}

/* ==========================================================================
   11. Card 6 — hatched gauges
   --------------------------------------------------------------------------
   The original ships two SVG files of 132 rounded strokes. One tile of 4 by 8
   with a single stroke, used as a mask, gives the same drawing for both
   colours and no request.
   ========================================================================== */

.dashboard-bento__gauges {
  display: grid;
  gap: var(--tb-content);
}

.dashboard-bento__region {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tb-region-gap);
  margin: 0;
  line-height: var(--tb-leading);
}

.dashboard-bento__region dt {
  color: var(--tb-text);
}

.dashboard-bento__region dd {
  margin: 0;
  color: var(--tb-title);
}

.dashboard-bento__gauge {
  position: relative;
  height: calc(0.5 * var(--tb-font-size));
  margin-top: calc(0.5 * var(--tb-font-size));
}

.dashboard-bento__gauge::before,
.dashboard-bento__gauge::after {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  -webkit-mask-image: var(--tb-hatch);
  mask-image: var(--tb-hatch);
  -webkit-mask-size: calc(0.25 * var(--tb-font-size)) 100%;
  mask-size: calc(0.25 * var(--tb-font-size)) 100%;
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  content: "";
}

.dashboard-bento {
  /* One tile: a 2-wide stroke with 1 of radius, in a 4-wide cell. */
  --tb-hatch: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="4" height="8"><rect width="2" height="8" rx="1" fill="%23000"/></svg>');
}

/* The hollow track is half a period out of step with the fill. That is not a
   flourish: the original stretches a 526-wide drawing into a narrower box and
   pins it to the right, which lands its strokes 2 px off. The effect — a grey
   hairline showing between the white strokes — is what one sees, so it is
   reproduced, and reproduced exactly: 526 is 2 more than a whole number of
   4-wide cells, so the offset is half a period whatever the width. */
.dashboard-bento__gauge::before {
  right: 0;
  background-color: var(--tb-line);
  -webkit-mask-position: calc(100% - 0.125 * var(--tb-font-size)) center;
  mask-position: calc(100% - 0.125 * var(--tb-font-size)) center;
}

.dashboard-bento__gauge::after {
  background-color: var(--tb-title);
}

.dashboard-bento__region + .dashboard-bento__gauge {
  margin-bottom: 0;
}

.dashboard-bento__gauge--1::after { width: var(--tb-gauge-1); }
.dashboard-bento__gauge--2::after { width: var(--tb-gauge-2); }
.dashboard-bento__gauge--3::after { width: var(--tb-gauge-3); }

/* ==========================================================================
   12. Entrance motion
   --------------------------------------------------------------------------
   The script adds .is-armed once it is running, which is what hides the
   blocks; without a script nothing is hidden and the section reads as it
   should. .is-in then plays them, in the order the original plays them.
   ========================================================================== */

.dashboard-bento.is-armed .dashboard-bento__title,
.dashboard-bento.is-armed .dashboard-bento__lead p,
.dashboard-bento.is-armed .dashboard-bento__actions,
.dashboard-bento.is-armed .dashboard-bento__card {
  opacity: 0;
}

.dashboard-bento.is-armed .dashboard-bento__title,
.dashboard-bento.is-armed .dashboard-bento__lead p {
  transform: translateY(5%);
}

.dashboard-bento.is-in .dashboard-bento__title,
.dashboard-bento.is-in .dashboard-bento__lead p,
.dashboard-bento.is-in .dashboard-bento__actions,
.dashboard-bento.is-in .dashboard-bento__card {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--tb-in-duration) var(--tb-ease),
    transform var(--tb-in-duration) var(--tb-ease);
}

.dashboard-bento.is-in .dashboard-bento__title { transition-delay: var(--tb-in-delay); }
.dashboard-bento.is-in .dashboard-bento__lead p { transition-delay: calc(var(--tb-in-delay) + var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__actions { transition-delay: calc(var(--tb-in-delay) + 2 * var(--tb-in-step)); }

/* The cards come in by column, one step apart, both grids at once. */
.dashboard-bento.is-in .dashboard-bento__card:nth-child(1) { transition-delay: calc(var(--tb-in-delay) + var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__card:nth-child(2) { transition-delay: calc(var(--tb-in-delay) + 2 * var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__card:nth-child(3) { transition-delay: calc(var(--tb-in-delay) + 3 * var(--tb-in-step)); }

/* Bars grow from nothing, a tenth of a second apart. */
.dashboard-bento.is-armed .dashboard-bento__bar { height: 0; }
.dashboard-bento.is-armed .dashboard-bento__bar::before { height: 0; }

.dashboard-bento.is-in .dashboard-bento__bar,
.dashboard-bento.is-in .dashboard-bento__bar::before {
  transition: height var(--tb-bar-duration) var(--tb-out-quart);
}

.dashboard-bento.is-in .dashboard-bento__bar:nth-child(1) { height: var(--tb-chart-1); transition-delay: var(--tb-in-delay); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(2) { height: var(--tb-chart-2); transition-delay: calc(var(--tb-in-delay) + var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(3) { height: var(--tb-chart-3); transition-delay: calc(var(--tb-in-delay) + 2 * var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(4) { height: var(--tb-chart-4); transition-delay: calc(var(--tb-in-delay) + 3 * var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(5) { height: var(--tb-chart-5); transition-delay: calc(var(--tb-in-delay) + 4 * var(--tb-in-step)); }

.dashboard-bento.is-in .dashboard-bento__bar::before { height: calc(0.125 * var(--tb-font-size)); }
.dashboard-bento.is-in .dashboard-bento__bar--full::before { height: 100%; }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(1)::before { transition-delay: calc(var(--tb-in-delay) + var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(2)::before { transition-delay: calc(var(--tb-in-delay) + 2 * var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(3)::before { transition-delay: calc(var(--tb-in-delay) + 3 * var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(4)::before { transition-delay: calc(var(--tb-in-delay) + 4 * var(--tb-in-step)); }
.dashboard-bento.is-in .dashboard-bento__bar:nth-child(5)::before { transition-delay: calc(var(--tb-in-delay) + 5 * var(--tb-in-step)); }

/* Columns rise, then fill from the left a beat later. */
.dashboard-bento.is-armed .dashboard-bento__column { transform: scaleY(0); }
.dashboard-bento.is-armed .dashboard-bento__column-fill { transform: scaleX(0); }

.dashboard-bento.is-in .dashboard-bento__column {
  transform: none;
  transition: transform var(--tb-column-duration) var(--tb-out-quart);
  transition-delay: calc(var(--tb-in-delay) + (var(--tb-index) - 1) * var(--tb-in-step));
}

.dashboard-bento.is-in .dashboard-bento__column-fill {
  transform: none;
  transition: transform var(--tb-column-duration) var(--tb-ease-out);
  transition-delay: calc(var(--tb-in-delay) + (var(--tb-index) + 1) * var(--tb-in-step));
}

.dashboard-bento__column:nth-child(1) { --tb-index: 1; }
.dashboard-bento__column:nth-child(2) { --tb-index: 2; }
.dashboard-bento__column:nth-child(3) { --tb-index: 3; }
.dashboard-bento__column:nth-child(4) { --tb-index: 4; }
.dashboard-bento__column:nth-child(5) { --tb-index: 5; }
.dashboard-bento__column:nth-child(6) { --tb-index: 6; }
.dashboard-bento__column:nth-child(7) { --tb-index: 7; }
.dashboard-bento__column:nth-child(8) { --tb-index: 8; }
.dashboard-bento__column:nth-child(9) { --tb-index: 9; }
.dashboard-bento__column:nth-child(10) { --tb-index: 10; }
.dashboard-bento__column:nth-child(11) { --tb-index: 11; }
.dashboard-bento__column:nth-child(12) { --tb-index: 12; }

/* Gauges: the hollow track draws itself first, the fill follows. */
.dashboard-bento.is-armed .dashboard-bento__gauge::before,
.dashboard-bento.is-armed .dashboard-bento__gauge::after { width: 0; }

.dashboard-bento.is-in .dashboard-bento__gauge::before {
  width: 100%;
  transition: width var(--tb-bar-duration) var(--tb-out-quart) var(--tb-in-delay);
}

.dashboard-bento.is-in .dashboard-bento__gauge::after {
  transition: width var(--tb-bar-duration) var(--tb-out-quart) calc(var(--tb-in-delay) + 2 * var(--tb-in-step));
}

.dashboard-bento.is-in .dashboard-bento__gauge--1::after { width: var(--tb-gauge-1); }
.dashboard-bento.is-in .dashboard-bento__gauge--2::after { width: var(--tb-gauge-2); }
.dashboard-bento.is-in .dashboard-bento__gauge--3::after { width: var(--tb-gauge-3); }

/* And the plain meter under the radar. */
.dashboard-bento.is-armed .dashboard-bento__meter::before { width: 0; }

.dashboard-bento.is-in .dashboard-bento__meter::before {
  width: var(--tb-ratio);
  transition: width var(--tb-bar-duration) var(--tb-out-quart) calc(var(--tb-in-delay) + 2 * var(--tb-in-step));
}

/* ==========================================================================
   13. Responsive steps
   --------------------------------------------------------------------------
   Container queries, not media queries: the block reacts to the width it is
   given, so it behaves the same in a page, in a column, or in a frame.
   The thresholds are the original's own.
   ========================================================================== */

@container dashboard-bento (max-width: 991px) {
  .dashboard-bento__container {
    --tb-pad-card: calc(1.625 * var(--tb-font-size));
    --tb-pad-card-bottom: calc(2 * var(--tb-font-size));
    --tb-pad-side: calc(1.25 * var(--tb-font-size));
    --tb-pad-top: calc(2.25 * var(--tb-font-size));
    --tb-row-gap-x: calc(1.25 * var(--tb-font-size));
    --tb-figure: calc(3 * var(--tb-font-size));
    --tb-max: calc(61.875 * var(--tb-font-size));
    --tb-stack: calc(2 * var(--tb-font-size));
    --tb-region-gap: calc(1.625 * var(--tb-font-size));
  }

  /* Two columns; the wide card goes last on the top grid, first on the
     bottom one — the original reorders them the same way. */
  .dashboard-bento__intro {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .dashboard-bento__actions {
    justify-content: center;
  }

  .dashboard-bento__grid--top {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  }

  .dashboard-bento__grid--bottom {
    grid-template-columns: minmax(0, 0.7fr) minmax(0, 1fr);
  }

  .dashboard-bento__card--raised {
    order: 1;
    grid-column: span 2;
  }

  .dashboard-bento__card--wide {
    order: -1;
    grid-column: span 2;
  }
}

@container dashboard-bento (max-width: 767px) {
  .dashboard-bento__container {
    --tb-pad-card: calc(1.25 * var(--tb-font-size));
    --tb-pad-card-bottom: calc(1.5 * var(--tb-font-size));
    --tb-pad-side: calc(1.125 * var(--tb-font-size));
    --tb-pad-top: calc(1.75 * var(--tb-font-size));
    --tb-row-gap-x: calc(1.125 * var(--tb-font-size));
    --tb-row-gap-y: calc(0.875 * var(--tb-font-size));
    --tb-figure: calc(2.5 * var(--tb-font-size));
    --tb-label: calc(0.875 * var(--tb-font-size));
    --tb-max: calc(47.9375 * var(--tb-font-size));
    --tb-stack: calc(1.5 * var(--tb-font-size));
    --tb-content: calc(1 * var(--tb-font-size));
    --tb-figure-lead: calc(2 * var(--tb-font-size));
    --tb-pad-button-y: calc(0.625 * var(--tb-font-size));
    --tb-region-gap: calc(1.25 * var(--tb-font-size));
  }

  /* The bottom grid falls back to two even columns: below this the first card
     no longer has the room for a radar. */
  .dashboard-bento__grid--bottom {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

@container dashboard-bento (max-width: 479px) {
  .dashboard-bento__container {
    --tb-pad-card: calc(1 * var(--tb-font-size));
    --tb-pad-card-bottom: calc(1.25 * var(--tb-font-size));
    --tb-pad-side: calc(1 * var(--tb-font-size));
    --tb-pad-top: calc(1.5 * var(--tb-font-size));
    --tb-row-gap-x: calc(1 * var(--tb-font-size));
    --tb-row-gap-y: calc(0.75 * var(--tb-font-size));
    --tb-figure: calc(1.45 * var(--tb-font-size));
    --tb-icon: calc(0.75 * var(--tb-font-size));
    --tb-max: calc(29.875 * var(--tb-font-size));
    --tb-stack: calc(1.25 * var(--tb-font-size));
    --tb-figure-lead: calc(1.35 * var(--tb-font-size));
    --tb-pad-button-y: calc(0.5 * var(--tb-font-size));
    --tb-region-gap: calc(1 * var(--tb-font-size));
  }

  /* A card this narrow cannot hold a label and a figure side by side. The
     original wraps this one row, and only this one. */
  .dashboard-bento__row--top {
    flex-wrap: wrap;
  }

  .dashboard-bento__columns {
    height: calc(4 * var(--tb-font-size));
  }
}

/* ==========================================================================
   14. Fallbacks
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  /* Delays are movement spread over time, so they go too. What is a picture
     and not a movement — the backdrop grid, the beam — stays. */
  .dashboard-bento *,
  .dashboard-bento *::before,
  .dashboard-bento *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }

  /* The beam is a shape, not a movement: it stays, where it starts. */
  .dashboard-bento__radar-sweep {
    transform: none;
  }
}

@media (forced-colors: active) {
  .dashboard-bento__card,
  .dashboard-bento__button {
    border: 1px solid CanvasText;
  }

  .dashboard-bento__bar,
  .dashboard-bento__column,
  .dashboard-bento__meter,
  .dashboard-bento__radar-ring,
  .dashboard-bento__radar-cross {
    forced-color-adjust: none;
    border-color: CanvasText;
    background-color: GrayText;
  }

  .dashboard-bento__bar::before,
  .dashboard-bento__column-fill,
  .dashboard-bento__meter::before,
  .dashboard-bento__beacon {
    forced-color-adjust: none;
    background-color: CanvasText;
  }

  /* A mask has no colour of its own to force: show the gauges as plain bars. */
  .dashboard-bento__gauge::before,
  .dashboard-bento__gauge::after {
    -webkit-mask-image: none;
    mask-image: none;
  }

  .dashboard-bento__gauge::before {
    forced-color-adjust: none;
    background-color: GrayText;
  }

  .dashboard-bento__gauge::after {
    forced-color-adjust: none;
    background-color: CanvasText;
  }
}
