/* ==========================================================================
   SUN Energy — benefits block, new design (Figma frame "Benefits v2 — 1920")
   A bento built to the stageshow rules: one hero tile, one stat, two
   diagrams and one component, copy on top of every tile, each picture pinned
   to its tile and cropped by it. Every quantity is drawn as dots. One warm
   accent (orange) for what the station gives you; blue for the grid, violet
   for what goes wrong (an outage, a generator).
   ========================================================================== */

:root {
  /* colour tokens, named as in the Figma Style Guide (collection "Tokens");
     the comment after each is its primitive */
  --bg-page: #02040a;                           /* neutral/950 */
  --bg-surface: #090b11;                        /* neutral/900: tiles, navbar */
  --bg-raised: #10131b;                         /* neutral/800: panels, menu */
  --bg-selected: #1b1f2a;                       /* neutral/700 */
  --bg-subtle: rgba(255, 255, 255, 0.04);       /* alpha-white/4 */
  --bg-muted: rgba(255, 255, 255, 0.08);        /* alpha-white/8 */
  --bg-accent: #f97316;                         /* orange/500 */
  --bg-inverse: #ffffff;                        /* base/white */

  --text-primary: #ffffff;                      /* base/white */
  --text-secondary: rgba(255, 255, 255, 0.7);   /* alpha-white/70 */
  --text-muted: rgba(255, 255, 255, 0.5);       /* alpha-white/50 */
  --text-accent: #f97316;                       /* orange/500 */
  --text-inverse: #02040a;                      /* neutral/950 */

  --border-default: rgba(255, 255, 255, 0.5);   /* alpha-white/50 */
  --border-subtle: rgba(255, 255, 255, 0.08);   /* alpha-white/8 */
  --border-raised: rgba(255, 255, 255, 0.1);    /* alpha-white/10 */
  --border-control: rgba(255, 255, 255, 0.14);  /* alpha-white/14 */
  --border-focus: #f97316;                      /* orange/500 */
  --border-highlight: rgba(255, 255, 255, 0.7); /* alpha-white/70 */

  /* the dot diagrams: orange is what the station gives, violet is what goes
     wrong, blue is the grid */
  --data-power: #f97316;                        /* orange/500 */
  --data-power-ray: #fdba74;                    /* orange/300, js/hero.js */
  --data-power-soft: rgba(249, 115, 22, 0.14);  /* alpha-orange-500/14 */
  --data-power-solid: rgba(249, 115, 22, 0.55); /* alpha-orange-500/55 */
  --data-outage: #a78bfa;                       /* violet/400 */
  --data-outage-soft: rgba(167, 139, 250, 0.24);   /* alpha-violet-400/24 */
  --data-outage-strong: rgba(167, 139, 250, 0.4);  /* alpha-violet-400/40 */
  --data-grid: #60a5fa;                         /* blue/400 */
  --data-dot-off: rgba(255, 255, 255, 0.08);    /* alpha-white/8 */

  /* type: Geist, as the Figma text styles */
  --font: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  --fs-h2: 48px;
  --fs-title: 24px;
  --lh-title: 31px;
  --fs-body: 20px;
  --lh-body: 26px;

  /* layout: collection "Layout" */
  --page-x: 100px;      /* space/page-x */
  --section-y: 120px;   /* space/section-y */
  --radius-panel: 20px; /* radius/panel */
  --radius-control: 12px; /* radius/control */

  /* one frame for all five tiles */
  --radius: 32px;
  --pad: 32px;          /* the copy gutter; every picture lines up with it */
  --gap: 16px;          /* half the padding */
  --art-gap: 32px;      /* copy to picture */

  /* motion (stageshow, references/motion.md): travel and arrival */
  --travel: cubic-bezier(0.45, 0, 0.1, 1);
  --arrive: cubic-bezier(0.25, 0.8, 0.25, 1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--bg-page);
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg-page);
  color: var(--text-primary);
  font-family: var(--font);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}

h2,
h3,
p {
  margin: 0;
}

b,
i {
  font: inherit;
}

::selection {
  background: var(--bg-accent);
  color: var(--text-inverse);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Section ---------- */
.benefits {
  max-width: 1920px;
  margin: 0 auto;
  padding: var(--section-y) var(--page-x);
}

.benefits__title {
  max-width: 584px;
  margin-bottom: 48px;
  font-weight: 600;
  font-size: var(--fs-h2);
  line-height: 1;                /* Heading/H2: 100 % */
  letter-spacing: -0.04em;
  text-wrap: balance;
}

/* ---------- Bento: hero and strip ---------- */
.bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: 420px 380px;
  grid-template-areas:
    "schedule schedule bills"
    "noise    switch   climate";
  gap: var(--gap);
}

.tile--schedule { grid-area: schedule; }
.tile--bills    { grid-area: bills; }
.tile--noise    { grid-area: noise; }
.tile--switch   { grid-area: switch; }
.tile--climate  { grid-area: climate; }

/* ---------- The tile ---------- */
.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  background: var(--bg-surface);
}

/* The stat is the one warm tile: the same surface, lit from below. On hover
   the light follows the pointer (js/benefits.js moves --gx, --gy). */
.tile--bills {
  --gx: 30%;
  --gy: 100%;
  --ga: 0.14;
  background:
    radial-gradient(90% 70% at var(--gx) var(--gy), rgba(249, 115, 22, var(--ga)), transparent 70%),
    var(--bg-surface);
}

.tile__copy {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 540px;
  padding: var(--pad) var(--pad) 0;
}

.tile__title {
  font-weight: 600;
  font-size: var(--fs-title);
  line-height: var(--lh-title);
  letter-spacing: -0.01em;      /* Title/M */
  text-wrap: balance;
}

.tile__desc {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: -0.01em;
  color: var(--text-secondary);
  text-wrap: pretty;
}

/* The picture: the tile below its copy. It owns the crop, so it carries the
   tile's bottom corners and nothing else clips. */
.tile__art {
  position: relative;
  flex: 1;
  min-height: 0;
  margin-top: var(--art-gap);
  overflow: hidden;
  border-radius: 0 0 calc(var(--radius) - 1px) calc(var(--radius) - 1px);
  font-variant-numeric: tabular-nums;
}

/* The pictures that reach the bottom of their tile fade out at its foot
   instead of being cut (a mask, so they dissolve into whatever is behind) */
.tile--schedule { --fade: 140px; }
.tile--switch { --fade: 80px; }
.tile--climate { --gauge-fade: 150px; }   /* the gauge fades its dots only, not its figure */

.tile--schedule .tile__art,
.tile--switch .tile__art {
  -webkit-mask-image: linear-gradient(#000 calc(100% - var(--fade)), transparent);
  mask-image: linear-gradient(#000 calc(100% - var(--fade)), transparent);
}

/* Reveal: each tile rises as it scrolls in, 110 ms after the one before it */
.js .tile {
  opacity: 0;
  transform: translateY(24px);
}

.js .tile.is-in {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.8s var(--arrive) calc(var(--i, 0) * 110ms),
    transform 0.9s var(--arrive) calc(var(--i, 0) * 110ms);
}

/* ---------- Shared parts ---------- */

/* A product surface: lighter than the tile, never a shadow (dark theme).
   Pinned a gutter from the left, right and top, it runs off the bottom. */
.panel {
  position: absolute;
  top: 0;
  left: var(--pad);
  right: var(--pad);
  height: calc(100% + 96px);
  border: 1px solid var(--border-raised);
  border-radius: var(--radius-panel);
  background: var(--bg-raised);
}

.panel__label {
  font-size: 15px;
  font-weight: 500;
  line-height: 20px;
  color: var(--text-secondary);
}

.dot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-muted);
}

.dot--orange { background: var(--data-power); }
.dot--blue   { background: var(--data-grid); }
.dot--violet { background: var(--data-outage); }

.bar {
  display: block;
  flex: none;
  width: var(--w, 40%);
  height: 8px;
  border-radius: 4px;
  background: var(--bg-muted);
}

.bar--end {
  width: 40px;
  margin-left: auto;
}

.log-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 20px;
}

.log-row__text {
  font-size: 15px;
  line-height: 20px;
  color: var(--text-primary);
}

.log-row__time {
  margin-left: auto;
  font-size: 14px;
  line-height: 18px;            /* UI/Caption */
  color: var(--text-muted);
}

/* Text that changes rolls: the old value leaves upward, the new arrives
   from below, inside a soft mask so no edge slices the glyphs. */
.roll {
  display: inline-grid;
  vertical-align: top;
}

.roll__item {
  grid-area: 1 / 1;
}

/* ---------- 1. Schedule (hero) ---------- */
.sched {
  display: flex;
  flex-direction: column;
  gap: 28px;
  padding: 22px 24px;
}

.sched__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.pill {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;               /* 28 px tall, its text inset on every side */
  border-radius: 999px;
  background: var(--bg-muted);
  font-size: 13px;
  font-weight: 500;
  line-height: 16px;
  will-change: transform;
}

.pill__text {
  white-space: pre;
}

.pill__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--data-power);
}

/* The hourly table: a row of hours, then one row per place, 24 cells each */
.sched__table {
  --cell-h: 36px;
  --cell-gap: 4px;
  --cell-r: 8px;
  --icon: 14px;
  position: relative;
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr);
  align-items: center;
  column-gap: 16px;
  row-gap: 6px;
}

.sched__name {
  font-size: 14px;
  line-height: 18px;
  color: var(--text-secondary);
}

.sched__hours,
.sched__cells {
  display: grid;
  grid-template-columns: repeat(24, minmax(0, 1fr));
  gap: var(--cell-gap);
}

.sched__hours {
  margin-bottom: 2px;
}

.sched__hours span {
  font-size: 12px;
  line-height: 16px;
  text-align: center;
  color: var(--text-muted);
  transition: color 0.2s linear;
}

.sched__hours span.is-now {
  color: var(--text-primary);
}

/* light: a warm cell with a bolt */
.cell {
  display: grid;
  place-items: center;
  height: var(--cell-h);
  border-radius: var(--cell-r);
  background: var(--data-power-soft);
  color: var(--data-power);
}

/* no light: a dark cell with a slashed bolt */
.cell.is-off {
  background: var(--bg-subtle);
  box-shadow: inset 0 0 0 1px var(--data-outage-soft);
  color: var(--data-outage);
}

.cell svg {
  display: block;
  width: var(--icon);
  height: var(--icon);
}

/* the hour we are in: one ring round its column, sliding hour to hour */
.sched__now {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: calc(var(--cell-r) + 4px);
  box-shadow: inset 0 0 0 1.5px var(--border-highlight);
  pointer-events: none;
  transition: transform 0.7s var(--travel), opacity 0.3s linear;
  will-change: transform;
}

.sched__now.is-jump {
  opacity: 0;
  transition: opacity 0.2s linear;
}

.sched__log {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.rule {
  display: block;
  flex: none;
  height: 1px;
  background: var(--border-raised);
}

/* ---------- 2. Bills (stat): 50–75% on a dot-matrix field ---------- */
.led {
  position: absolute;
  inset: 0;
}

/* the unlit field: one dot per pitch, fading out toward the edges; the
   number sits in its middle, unmasked */
.led__field {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, var(--data-dot-off) calc(var(--led-dot, 10px) / 2 - 0.5px), transparent calc(var(--led-dot, 10px) / 2));
  background-size: var(--led-pitch, 14px) var(--led-pitch, 14px);
  background-position: var(--led-x, 0) var(--led-y, 0);
  -webkit-mask-image: radial-gradient(closest-side, #000 40%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 40%, transparent 100%);
}

.led .px {
  position: absolute;
  width: var(--led-dot, 10px);
  height: var(--led-dot, 10px);
  border-radius: 50%;
  background: var(--data-dot-off);
  transition: background-color 0.3s linear, box-shadow 0.3s linear;
}

/* the number lights column by column, left to right */
.led.is-lit .px {
  background: var(--data-power);
  box-shadow: 0 0 6px rgba(249, 115, 22, 0.35);   /* effect Glow/Lit dot */
  transition-delay: calc(var(--c) * 22ms);
}

/* ---------- 3. Noise (diagram) ---------- */
/* sits on the bottom gutter, like the gauge beside it */
.noise {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 10px;
  padding: 0 0 var(--pad) var(--pad);
}

.noise__name {
  font-size: 14px;
  line-height: 18px;
  color: var(--text-secondary);
}

/* 12, so the flat line lands on the same 10 px grid as the waveform and the
   unlit field behind them */
.noise__name + .wave + .noise__name {
  margin-top: 12px;
}

/* columns of dots, running off the tile's right edge */
.wave {
  --pitch: 10px;
  --wd: 6px;
  display: flex;
  align-items: center;
  gap: calc(var(--pitch) - var(--wd));
  height: calc(var(--pitch) * 9);
}

.wave--flat {
  height: var(--pitch);
}

.wave .col {
  display: flex;
  flex: none;
  flex-direction: column;
  gap: calc(var(--pitch) - var(--wd));
}

.wave .d {
  width: var(--wd);
  height: var(--wd);
  border-radius: 50%;
  background: var(--data-outage);
}

.wave--flat .d {
  background: var(--data-power);
}

/* the loud waveform grows out of the line, column by column */
.wave .d[data-k] {
  opacity: 0;
  transform: scale(0.4);
  transition:
    opacity 0.45s var(--arrive),
    transform 0.6s var(--arrive);
  transition-delay: calc(var(--c) * 14ms + var(--k) * 40ms);
}

.wave.is-loud .d[data-k].is-on {
  opacity: 1;
  transform: none;
}

/* then it keeps running: each column swells and settles, drawn frame by
   frame from a smooth level (js/benefits.js), so no transition here */
.wave.is-live .d[data-k] {
  transition: none;
}

/* ---------- 4. Switch (component) ---------- */
.source {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px 20px;
}

.source__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 500;
  line-height: 18px;
}

.toggle__track {
  position: relative;
  display: block;
  width: 32px;
  height: 18px;
  border-radius: 999px;
  background: var(--data-power);
}

.toggle__knob {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--bg-inverse);
}

/* two sources, one chosen; the choice slides */
.seg {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-radius: var(--radius-control);
  background: var(--bg-subtle);
}

.seg__thumb {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 50%;
  border-radius: var(--radius-control);
  background: var(--bg-selected);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
  transition: transform 0.5s var(--travel);
}

.seg[data-on="battery"] .seg__thumb {
  transform: translateX(100%);
}

.seg__opt {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 40px;
  font-size: 15px;
  font-weight: 500;
  line-height: 20px;            /* UI/Label */
  color: var(--text-secondary);
  transition: color 0.15s linear;
}

.seg[data-on="mains"] [data-opt="mains"],
.seg[data-on="battery"] [data-opt="battery"] {
  color: var(--text-primary);
}

.source__log {
  display: flex;
  flex-direction: column;
  padding-top: 4px;
}

/* each row carries the air below it, so a row that opens brings its own */
.source__log > .log-row,
.log-new__inner > .log-row {
  padding-bottom: 14px;
}

.source__log > .rule {
  margin-bottom: 14px;
}

.source__log .bar {
  height: 8px;
}

/* the new event opens its own room; the rows below move down with it */
.log-new {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 0.45s var(--travel);
}

.log-new__inner {
  min-height: 0;
  overflow: hidden;
}

.log-new__inner > .log-row {
  transition: opacity 0.3s linear 0.2s;
}

.log-new.is-closed {
  grid-template-rows: 0fr;
}

.log-new.is-closed .log-new__inner > .log-row {
  opacity: 0;
  transition-delay: 0s;
}

/* ---------- 5. Climate (diagram) ---------- */
.gauge {
  position: absolute;
  inset: 0;
}

.gauge__fade {
  position: absolute;
  inset: 0;
  -webkit-mask-image: linear-gradient(#000 calc(100% - var(--gauge-fade)), transparent);
  mask-image: linear-gradient(#000 calc(100% - var(--gauge-fade)), transparent);
}

.gauge__dots .d {
  position: absolute;
  width: var(--gd, 8px);
  height: var(--gd, 8px);
  margin: calc(var(--gd, 8px) / -2) 0 0 calc(var(--gd, 8px) / -2);
  border-radius: 50%;
  background: var(--data-dot-off);
  transition: background-color 0.3s linear;
}

/* the range lights from −20 to 60 °C, spoke by spoke */
.gauge.is-lit .d {
  background: var(--on);
  transition-delay: calc(var(--s) * 22ms);
}

/* then it shimmers: a soft wave of light runs from the cold end to the hot one */
@keyframes gauge-shimmer {
  0%, 100% { opacity: 0.55; transform: scale(0.9); }
  50% { opacity: 1; transform: scale(1.15); }
}

.gauge.is-live .d {
  animation: gauge-shimmer 2.8s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  animation-delay: calc(var(--s) * 90ms + var(--r) * 160ms - 5.6s);
}

.gauge.is-live.is-paused .d {
  animation-play-state: paused;
}

/* centred in the arc's open middle (js/benefits.js sets its top) */
.gauge__value {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 40px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  white-space: nowrap;
}

/* ==========================================================================
   Tablet: two columns, the hero across the top, then pairs
   ========================================================================== */
@media (max-width: 1279px) {
  :root {
    --fs-h2: 40px;
    --fs-title: 22px;
    --lh-title: 29px;
    --fs-body: 18px;
    --lh-body: 24px;
    --pad: 28px;
    --art-gap: 28px;
    --page-x: 40px;
    --section-y: 80px;
  }

  .benefits { padding: var(--section-y) var(--page-x); }
  .benefits__title { margin-bottom: 40px; }

  .bento {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: 420px 380px 380px;
    grid-template-areas:
      "schedule schedule"
      "bills    noise"
      "switch   climate";
  }

  .sched__table {
    --cell-h: 30px;
    --cell-gap: 3px;
    --cell-r: 7px;
    --icon: 12px;
    grid-template-columns: 72px minmax(0, 1fr);
    column-gap: 12px;
  }
}

/* narrow tablets: the hour labels every three hours */
@media (max-width: 1023px) {
  .sched__hours span:not(:nth-child(3n + 1)) { visibility: hidden; }
}

/* ==========================================================================
   Mobile: one column, hero first; the schedule recomposed for 358
   ========================================================================== */
@media (max-width: 767px) {
  :root {
    --fs-h2: 28px;
    --fs-title: 20px;
    --lh-title: 26px;
    --fs-body: 16px;
    --lh-body: 21px;
    --pad: 20px;
    --art-gap: 24px;
    --radius: 28px;
    --page-x: 16px;
    --section-y: 64px;
    --radius-panel: 16px;
  }

  .benefits__title { margin-bottom: 28px; }

  .bento {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 400px 320px 330px 350px 330px;
    grid-template-areas: "schedule" "bills" "noise" "switch" "climate";
  }

  /* compact schedule: names above their rows, thin cells, no icons,
     the hours every six */
  .sched { gap: 20px; padding: 16px; }
  .sched__table {
    --cell-h: 24px;
    --cell-gap: 2px;
    --cell-r: 4px;
    grid-template-columns: minmax(0, 1fr);
    row-gap: 6px;
  }
  /* one row only: the panel's title names it, the hours sit right on the cells */
  .sched__table > .sched__name { display: none; }
  .sched__name { font-size: 13px; line-height: 16px; }
  .sched__cells + .sched__name { margin-top: 4px; }
  /* too narrow for icons: the fill alone says it, both states filled */
  .cell svg { display: none; }
  .cell { background: var(--data-power-solid); }
  .cell.is-off {
    background: var(--data-outage-soft);
    box-shadow: inset 0 0 0 1px var(--data-outage-strong);
  }
  .sched__hours span:not(:nth-child(6n + 1)) { visibility: hidden; }
  /* the names sit between the rows here, so the hour is ringed cell by cell */
  .sched__now { display: none; }
  .cell { transition: box-shadow 0.2s linear; }
  .cell.is-now { box-shadow: inset 0 0 0 1.5px var(--border-highlight); }
  .sched__log { gap: 16px; }

  .source { gap: 14px; padding: 14px 16px; }
  .seg__opt { height: 38px; font-size: 14px; line-height: 18px; }   /* UI/Label S */

  .gauge__value { font-size: 32px; }
  .tile--climate { --gauge-fade: 110px; }
}

/* posters only: reduced motion, or a still being filmed */
.is-still .js .tile,
.is-still.js .tile,
.is-still .tile *,
.is-still .tile *::before,
.is-still .tile *::after {
  transition: none !important;
  animation: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .js .tile,
  .js .tile.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .tile *,
  .tile *::before,
  .tile *::after {
    transition: none !important;
    animation: none !important;
  }
}
