/* ============================================================
   menu.css — the menu shell: grid, channels, curved bar, pointer
   ============================================================ */

/* ---------- Frutiger Aero background drift ----------
   Ten bubbles, transform + opacity only, so they ride the compositor
   and never touch layout. Hidden entirely when motion is reduced. */
.aero {
  position: fixed;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
}
.aero span {
  position: absolute;
  bottom: -18vh;
  border-radius: 50%;
  /* a touch more body than before, so they are worth aiming at */
  background:
    radial-gradient(circle at 32% 26%,
      rgba(255, 255, 255, .96) 0%,
      rgba(206, 236, 252, .56) 40%,
      rgba(120, 190, 232, .24) 66%,
      rgba(120, 190, 232, .08) 78%,
      transparent 80%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .55),
    inset 0 0 14px rgba(255, 255, 255, .75),
    0 2px 6px rgba(80, 140, 180, .12);
  animation: rise linear infinite;
  will-change: transform, opacity;
}
@keyframes rise {
  0%   { transform: translate3d(0, 0, 0) scale(.9); opacity: 0; }
  12%  { opacity: .9; }
  88%  { opacity: .55; }
  100% { transform: translate3d(var(--dx, 24px), -128vh, 0) scale(1.18); opacity: 0; }
}

/* The pop. --at is the transform the rise animation had reached when it
   was clicked (set by app.js), so the burst happens where the bubble was. */
.aero span.is-popping {
  animation: pop 380ms cubic-bezier(.2, .7, .2, 1) forwards;
  box-shadow:
    inset 0 0 0 2px rgba(255, 255, 255, .9),
    0 0 0 0 rgba(255, 255, 255, .8);
}
@keyframes pop {
  0%   { transform: var(--at) scale(1);    opacity: .95; }
  35%  { transform: var(--at) scale(1.32); opacity: .8;  box-shadow: inset 0 0 0 2px rgba(255,255,255,.9), 0 0 0 6px rgba(255,255,255,.35); }
  100% { transform: var(--at) scale(1.75); opacity: 0;   box-shadow: inset 0 0 0 1px rgba(255,255,255,0), 0 0 0 18px rgba(255,255,255,0); }
}
.aero span:nth-child(1)  { left:  6%; width: 46px; height: 46px; --dx:  30px; animation-duration: 21s; animation-delay:  -2s; }
.aero span:nth-child(2)  { left: 17%; width: 22px; height: 22px; --dx: -18px; animation-duration: 16s; animation-delay:  -9s; }
.aero span:nth-child(3)  { left: 28%; width: 64px; height: 64px; --dx:  40px; animation-duration: 27s; animation-delay: -14s; }
.aero span:nth-child(4)  { left: 39%; width: 30px; height: 30px; --dx: -26px; animation-duration: 19s; animation-delay:  -5s; }
.aero span:nth-child(5)  { left: 51%; width: 52px; height: 52px; --dx:  22px; animation-duration: 24s; animation-delay: -18s; }
.aero span:nth-child(6)  { left: 63%; width: 26px; height: 26px; --dx: -32px; animation-duration: 17s; animation-delay: -11s; }
.aero span:nth-child(7)  { left: 72%; width: 58px; height: 58px; --dx:  34px; animation-duration: 25s; animation-delay:  -7s; }
.aero span:nth-child(8)  { left: 83%; width: 34px; height: 34px; --dx: -20px; animation-duration: 20s; animation-delay: -16s; }
.aero span:nth-child(9)  { left: 91%; width: 44px; height: 44px; --dx:  28px; animation-duration: 23s; animation-delay:  -3s; }
.aero span:nth-child(10) { left: 46%; width: 18px; height: 18px; --dx:  16px; animation-duration: 15s; animation-delay: -12s; }

/* fewer bubbles to composite on phones */
@media (max-width: 620px) {
  .aero span:nth-child(n + 6) { display: none; }
}
@media (prefers-reduced-motion: reduce) { .aero { display: none; } }
html.reduce-motion .aero { display: none; }

/* ---------- the menu plane ---------- */
body {
  background:
    radial-gradient(130% 90% at 50% -20%, #ffffff 0%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(var(--bg-1) 0%, #edf1f3 45%, var(--bg-2) 100%);
  background-attachment: fixed;
}

/* The faint horizontal lines. This is the detail that dates the whole thing:
   the original menu was drawn for a CRT, and the background carries a fine 3px
   scanline stripe over the gradient. Sits under the menu, which is transparent,
   so it shows through the gaps and through the empty slots. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, .55) 0px,
    rgba(255, 255, 255, .55) 1px,
    rgba(138, 150, 158, .085) 1px,
    rgba(138, 150, 158, .085) 3px
  );
}
/* on a very high-density screen a 3px period starts to shimmer, so stretch it */
@media (min-resolution: 2dppx) {
  body::before {
    background: repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, .5) 0px,
      rgba(255, 255, 255, .5) 1.5px,
      rgba(138, 150, 158, .08) 1.5px,
      rgba(138, 150, 158, .08) 4px
    );
  }
}
html:not(.js) body::before { display: none; }

.menu {
  position: relative;
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 2.4vh, 26px);
  padding: clamp(20px, 4vh, 40px) clamp(12px, 3vw, 32px);
  padding-bottom: calc(var(--bar-h) + clamp(20px, 4vh, 40px));
}
.js .menu { position: fixed; inset: 0; overflow-y: auto; }
.js .menu.is-behind { pointer-events: none; }

.menu__title { display: grid; gap: 2px; text-align: center; margin: 0; }
.menu__name {
  font-size: clamp(20px, 2.4vw, 28px);
  color: var(--ink);
  text-shadow: 0 1px 0 #fff;
}
.menu__role {
  font-size: clamp(11px, 1.2vw, 13px);
  color: var(--ink-soft);
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* ---------- the channel grid ---------- */
.grid-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.6vw, 20px);
  width: 100%;
}

/* dimmed page arrows: set dressing, and honest about there being one page */
.pager {
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(22px, 2.4vw, 30px);
  color: #8fb9d0;
  opacity: .42;
}
.pager svg { width: 100%; height: auto; }
@media (max-width: 700px) { .pager { display: none; } }

.grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(10px, 1.6vw, 20px);
  width: min(980px, 94vw);
  grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 620px) {
  /* Six channels, three across, two down. No half-empty last row. */
  .grid { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 860px) {
  /* Keep every tile on one screen the way the real console does: the grid can
     never grow taller than the space between the title and the bar.
     Three 4:3 tiles across by two down is an aspect ratio of 2:1. */
  .grid { width: min(980px, 94vw, calc((100svh - var(--bar-h) - 190px) * 2)); }
}

.slot { display: block; min-width: 0; }

/* Empty slots read as recessed wells with the background stripe showing
   through — the console always looked half-unpacked, and that is the point. */
.slot--empty {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius);
  background: linear-gradient(rgba(255, 255, 255, .42), rgba(255, 255, 255, .06));
  border: 2px solid rgba(255, 255, 255, .85);
  box-shadow:
    0 0 0 1px rgba(150, 178, 194, .5),
    inset 0 3px 9px rgba(60, 100, 125, .16);
}

/* the channels dropping in on load, one after another, the way the menu
   assembled itself after the health-and-safety screen */
@media (prefers-reduced-motion: no-preference) {
  .js .slot { animation: slot-in 400ms var(--ease-pop) both; }
  .js .slot:nth-child(1)  { animation-delay:  40ms; }
  .js .slot:nth-child(2)  { animation-delay:  80ms; }
  .js .slot:nth-child(3)  { animation-delay: 120ms; }
  .js .slot:nth-child(4)  { animation-delay: 160ms; }
  .js .slot:nth-child(5)  { animation-delay: 200ms; }
  .js .slot:nth-child(6)  { animation-delay: 240ms; }
  .js .slot:nth-child(7)  { animation-delay: 280ms; }
  .js .slot:nth-child(8)  { animation-delay: 320ms; }
  .js .slot:nth-child(9)  { animation-delay: 360ms; }
  .js .slot:nth-child(10) { animation-delay: 400ms; }
  .js .slot:nth-child(11) { animation-delay: 440ms; }
  .js .slot:nth-child(12) { animation-delay: 480ms; }
}
@keyframes slot-in {
  from { opacity: 0; transform: scale(.86) translateY(7px); }
  to   { opacity: 1; transform: none; }
}
html.reduce-motion .slot { animation: none !important; opacity: 1; transform: none; }

/* The boot stagger is a once-per-visit thing. data.js re-renders the grid
   when content.json loads, and without this the tiles would drop in a second
   time, a beat after they had already settled. */
html.is-booted .slot { animation: none !important; }

/* ============================================================
   A CHANNEL
   Desktop: banner art with a white name band inside the tile.
   Phone:   square banner, name sitting underneath it.
   ============================================================ */
.chan {
  position: relative;
  display: flex;
  flex-direction: column;
  aspect-ratio: 4 / 3;
  text-decoration: none;
  color: var(--ink);
  background: var(--paper);
  /* white moulded bevel with a hairline outside it — the console's tile edge */
  border: 2px solid #ffffff;
  border-radius: var(--radius);
  box-shadow:
    0 0 0 1px #9db6c4,
    0 3px 6px rgba(45, 85, 110, .22);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}

.chan__art {
  position: relative;
  flex: 1 1 auto;
  display: grid;
  place-items: center;
  min-height: 0;
  overflow: hidden;
  /* The banner, with the same fine scanline laid over it. --from and --to
     come from the channel in content.json, so a colour changed in the editor
     lands here with no CSS to edit. */
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, .11) 0px, rgba(255, 255, 255, .11) 1px,
      rgba(0, 0, 0, .03) 1px, rgba(0, 0, 0, .03) 3px),
    linear-gradient(150deg, var(--from, #ffffff), var(--to, #e2edf4));
}
/* The icon sits on a white disc rather than straight on the banner, so it
   stays legible whether the channel colour is navy or cream. */
.chan__art svg {
  /* Sized from the height with aspect-ratio, so the disc is a circle.
     Percentage width and height resolve against different axes, which
     is what turned it into an ellipse. */
  height: 56%;
  width: auto;
  aspect-ratio: 1 / 1;
  box-sizing: border-box;
  padding: clamp(9px, 1.5vw, 17px);
  color: #2b3d47;
  background: rgba(255, 255, 255, .88);
  border-radius: 50%;
  box-shadow: 0 2px 6px rgba(20, 45, 65, .28), inset 0 0 0 1px rgba(255, 255, 255, .9);
  transition: transform var(--t-mid) var(--ease-pop);
}

/* the glass highlight across the top of the banner */
.chan__art::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 56%;
  border-radius: 0 0 48% 48% / 0 0 30% 30%;
  /* Kept lighter than the console's true gloss on purpose: at .92 the top half of
     every tile washed to near-white and the channel colours stopped
     telling them apart, which is the one thing the grid has to do. */
  background: linear-gradient(
    rgba(255, 255, 255, .62) 0%,
    rgba(255, 255, 255, .34) 42%,
    rgba(255, 255, 255, .06) 100%);
  pointer-events: none;
}
/* the shine that sweeps across on hover */
.chan__art::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .6) 50%, transparent 62%);
  transform: translateX(-130%);
  transition: transform var(--t-slow) var(--ease);
}

.chan__label {
  flex: none;
  padding: .55em .4em;
  text-align: center;
  font-size: clamp(10px, 1.05vw, 14px);
  line-height: 1.25;
  color: var(--ink);
  background: linear-gradient(#ffffff, #eaf2f7);
  border-top: 1px solid rgba(255, 255, 255, .9);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chan__badge {
  position: absolute;
  top: 7px; left: 7px;
  z-index: 3;
  font-size: 9px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(26, 146, 201, .92);
  padding: 2px 7px;
  border-radius: 999px;
}

/* hover / focus */
.chan:hover, .chan:focus-visible {
  transform: translateY(-4px) scale(1.04);
  box-shadow:
    0 0 0 1px var(--accent),
    0 0 0 5px var(--glow),
    0 12px 24px rgba(30, 80, 110, .24);
}
.chan:hover .chan__art::after,
.chan:focus-visible .chan__art::after { transform: translateX(130%); }
.chan:hover .chan__art svg,
.chan:focus-visible .chan__art svg { transform: scale(1.09); }
.chan:active { transform: translateY(-1px) scale(.995); }

/* A channel with artwork: the picture becomes the banner, with the colour
   gradient laid over it thinly so the icon disc and label still read. */
.chan--art .chan__art {
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, .11) 0px, rgba(255, 255, 255, .11) 1px,
      rgba(0, 0, 0, .03) 1px, rgba(0, 0, 0, .03) 3px),
    linear-gradient(150deg, color-mix(in srgb, var(--from, #fff) 28%, transparent),
                            color-mix(in srgb, var(--to, #dfeaf1) 34%, transparent)),
    var(--art) center 28% / cover no-repeat,
    linear-gradient(150deg, var(--from, #ffffff), var(--to, #e2edf4));
}
.chan--art .chan__art::before { height: 40%; opacity: .7; }

/* The Secret tile arrives with its own flourish, and the boot-stagger
   suppression (html.is-booted) is not allowed to take that away. */
html.is-booted .slot--secret { animation: secret-in 620ms var(--ease-pop) both !important; }
@keyframes secret-in {
  0%   { opacity: 0; transform: scale(.4) rotate(-8deg); }
  60%  { opacity: 1; transform: scale(1.08) rotate(2deg); }
  100% { opacity: 1; transform: none; }
}
.slot--secret .chan__badge { background: rgba(61, 42, 115, .92); }

/* The tiles used to drift up and down on a loop. Six of them doing that at
   once fought with the background and made the grid hard to read, so the
   motion now only happens under the pointer, where it means something. */

/* ---------- phone: square banners, names underneath ---------- */
@media (max-width: 559px) {
  .grid { gap: 12px 10px; }
  .slot--empty { display: none; }

  .chan {
    aspect-ratio: auto;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
    gap: 6px;
  }
  .chan__art {
    aspect-ratio: 1 / 1;
    flex: none;
    border: 2px solid var(--line);
    border-radius: 14px;
    box-shadow: 0 2px 5px rgba(45, 85, 110, .18);
  }
  .chan__label {
    padding: 0;
    background: none;
    border: 0;
    font-size: 11px;
    line-height: 1.3;
    white-space: normal;
    color: var(--ink-soft);
  }
  .chan:hover, .chan:focus-visible { transform: none; box-shadow: none; }
  .chan:focus-visible .chan__art { box-shadow: 0 0 0 4px var(--glow); }
  .chan__badge { top: 5px; left: 5px; }
}

/* ---------- keyboard hint ---------- */
.menu__hint {
  margin: 0;
  font-size: 12px;
  color: var(--ink-soft);
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
}
.menu__hint .key {
  display: inline-block;
  font-family: var(--mono);
  font-size: 11px;
  background: rgba(255, 255, 255, .9);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 5px;
  padding: 1px 6px;
  margin-right: 5px;
  color: var(--ink);
}
@media (hover: none) { .menu__hint { display: none; } }

/* ============================================================
   THE BAR — curved lip, orbs, clock
   ============================================================ */
.bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;
  height: calc(var(--bar-h) + env(safe-area-inset-bottom, 0px));
  padding: 0 clamp(10px, 2.4vw, 26px) env(safe-area-inset-bottom, 0px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.bar__curve {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  filter: drop-shadow(0 -2px 6px rgba(25, 60, 85, .14));
}

.bar__side { display: flex; align-items: center; gap: clamp(6px, 1.2vw, 12px); }
.bar__side--end { justify-content: flex-end; }

/* the menu back button: takes the photo orb's place inside a channel */
.bar__back {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  min-height: 46px;
  padding: 0 1.1em 0 .7em;
  font: inherit;
  font-size: clamp(13px, 1.4vw, 15px);
  color: var(--ink);
  background: linear-gradient(#ffffff, #dde7ed);
  border: 2px solid #ffffff;
  border-radius: 999px;
  box-shadow: 0 0 0 2px #9fc9e0, 0 2px 6px rgba(30, 70, 95, .3), inset 0 1px 0 #fff;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.bar__back[hidden] { display: none; }
.bar__back:hover, .bar__back:focus-visible {
  transform: translateY(-2px);
  color: var(--accent-hi);
  box-shadow: 0 0 0 2px var(--accent-lo), 0 0 0 6px var(--glow), 0 4px 10px rgba(30, 70, 95, .3), inset 0 1px 0 #fff;
}
.bar__back:active { transform: translateY(0); }

/* inside a channel the photo orb steps aside for the back button, and the
   clock goes away entirely — it sits in the transparent dip of the curve,
   so over a dark channel it would just float on top of the content. */
html.in-channel .orb--me { display: none; }
html.in-channel .bar__clock { display: none; }

/* ---------- the glossy orbs ---------- */
.orb {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: var(--orb, clamp(52px, 7.6vh, 74px));
  height: var(--orb, clamp(52px, 7.6vh, 74px));
  margin-top: calc(var(--orb, 64px) * -.16);
  border-radius: 50%;
  overflow: hidden;
  text-decoration: none;
  color: var(--ink-soft);
  background: radial-gradient(circle at 50% 20%, #ffffff 0%, #f1f6f9 42%, #cbd8e0 100%);
  border: 2px solid #ffffff;
  box-shadow:
    0 0 0 2px #9fc9e0,
    0 3px 8px rgba(25, 65, 90, .32),
    inset 0 -7px 12px rgba(140, 170, 188, .3);
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
.orb:hover, .orb:focus-visible {
  transform: translateY(-3px) scale(1.06);
  box-shadow:
    0 0 0 2px var(--accent-lo),
    0 0 0 7px var(--glow),
    0 6px 14px rgba(25, 65, 90, .34),
    inset 0 -7px 12px rgba(140, 170, 188, .3);
  color: var(--accent-hi);
}
.orb:active { transform: translateY(-1px) scale(1.01); }

.orb--me img { width: 100%; height: 100%; object-fit: cover; }

.orb__ico { display: block; width: 52%; height: 52%; color: var(--ink-soft); }
.orb__ico svg { width: 100%; height: 100%; display: block; }
.orb:hover .orb__ico, .orb:focus-visible .orb__ico { color: var(--accent-hi); }

/* the specular sheen sitting on top of everything inside the orb */
.orb__gloss {
  position: absolute;
  top: 5%; left: 12%;
  width: 76%; height: 44%;
  border-radius: 50%;
  background: linear-gradient(rgba(255, 255, 255, .92), rgba(255, 255, 255, .12));
  pointer-events: none;
}

/* the message count sits under the envelope, the way the console showed it */
.orb--mail .orb__ico { width: 46%; height: 46%; transform: translateY(-11%); }
.orb__badge {
  position: absolute;
  left: 50%; bottom: 11%;
  transform: translateX(-50%);
  min-width: 17px;
  padding: 0 4px;
  font-size: 10.5px;
  line-height: 16px;
  text-align: center;
  color: #fff;
  background: #f4526a;
  border: 1.5px solid #fff;
  border-radius: 999px;
  box-shadow: 0 1px 2px rgba(120, 20, 40, .35);
}

/* soft breathing glow, because Frutiger Aero never sat still */
@media (prefers-reduced-motion: no-preference) {
  .orb::after {
    content: "";
    position: absolute;
    inset: -2px;
    border-radius: 50%;
    box-shadow: 0 0 0 0 rgba(90, 190, 235, .5);
    animation: orb-pulse 4.5s ease-in-out infinite;
    pointer-events: none;
  }
  .orb--mail::after { animation-delay: -2.2s; }
}
@keyframes orb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(90, 190, 235, 0); }
  50%      { box-shadow: 0 0 12px 2px rgba(90, 190, 235, .45); }
}
html.reduce-motion .orb::after { animation: none; }

/* ---------- the small round button (old SD card slot) ---------- */
.bar__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  font: inherit;
  color: var(--ink-soft);
  background: linear-gradient(#ffffff, #dde7ed);
  border: 2px solid #ffffff;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(30, 70, 95, .3), inset 0 1px 0 #fff;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.bar__btn:hover, .bar__btn:focus-visible {
  transform: translateY(-2px);
  color: var(--accent-hi);
  box-shadow: 0 0 0 4px var(--glow), 0 4px 10px rgba(30, 70, 95, .3), inset 0 1px 0 #fff;
}
.bar__btn:active { transform: translateY(0); }
.bar__ico { display: block; width: 20px; height: 20px; }
.bar__ico svg { width: 100%; height: 100%; display: block; }

/* ---------- the clock, sitting in the dip of the curve ---------- */
.bar__clock {
  position: absolute;
  left: 50%;
  top: 6%;
  transform: translateX(-50%);
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 0;
  color: #8b9aa4;
  white-space: nowrap;
  pointer-events: none;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .85);
}
.bar__time { display: flex; align-items: flex-end; gap: .35em; }

/* the segmented display */
.seg {
  display: block;
  height: clamp(24px, 4.2vh, 40px);
  width: auto;
  overflow: visible;
}
.seg .s {
  stroke: #7d8d97;
  stroke-width: 3.6;
  stroke-linecap: round;
  opacity: .11;             /* unlit segments stay faintly visible */
}
.seg .s.on { opacity: 1; }
.seg .colon circle { fill: #7d8d97; }

.bar__ampm {
  font-size: clamp(10px, 1.4vh, 13px);
  letter-spacing: .1em;
  color: #8b9aa4;
  padding-bottom: .35em;
}
.bar__date {
  font-size: clamp(11px, 1.5vh, 15px);
  line-height: 1.25;
  letter-spacing: .03em;
  color: #8b9aa4;
}
@media (max-width: 420px) { .bar__date { display: none; } }
/* nothing sets the time without JS, so do not show an empty clock */
html:not(.js) .bar__clock { display: none; }

/* ============================================================
   OPTIONS PANEL
   ============================================================ */
.options {
  position: fixed;
  left: clamp(10px, 2.4vw, 26px);
  bottom: calc(var(--bar-h) + env(safe-area-inset-bottom, 0px) + 6px);
  z-index: 70;
  width: min(310px, calc(100vw - 24px));
  padding: 18px 20px;
  background: var(--paper);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 14px 40px rgba(20, 55, 80, .28);
  animation: pop-up var(--t-mid) var(--ease-pop) both;
}
.options[hidden] { display: none; }
@keyframes pop-up {
  from { opacity: 0; transform: translateY(10px) scale(.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.options h2 { font-size: 16px; margin-bottom: .8em; }
.options ul { list-style: none; margin: 0 0 .8em; padding: 0; display: grid; gap: 4px; }
.options label {
  display: flex;
  align-items: center;
  gap: .65em;
  min-height: 44px;
  padding: 0 .3em;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: .95em;
}
.options label:hover { background: #eef6fa; }
.options input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent); flex: none; }
.options em { color: var(--ink-soft); font-size: .85em; font-style: normal; }
.options__note { font-size: 12px; color: var(--ink-soft); margin-bottom: 1em; }

/* ============================================================
   LIGHTBOX
   ============================================================ */
.lightbox {
  position: fixed; inset: 0; z-index: 90;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(4px, 2vw, 20px);
  padding: clamp(12px, 4vw, 40px);
  background: rgba(10, 18, 24, .93);
  animation: fade-in var(--t-mid) var(--ease) both;
}
.lightbox[hidden] { display: none; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.lb__fig { margin: 0; display: grid; gap: 14px; justify-items: center; min-width: 0; }
.lb__fig img {
  max-width: 100%;
  max-height: 72svh;
  width: auto;
  border-radius: var(--radius-sm);
  background: #000;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .6);
}
.lb__fig figcaption {
  color: #e6eef3;
  font-size: .95em;
  text-align: center;
  max-width: 60ch;
}
.lb__nav, .lb__close {
  display: grid; place-items: center;
  width: 52px; height: 52px;
  font-size: 30px; line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, .1);
  border: 2px solid rgba(255, 255, 255, .38);
  border-radius: 50%;
  cursor: pointer;
}
.lb__nav:hover, .lb__close:hover { background: rgba(255, 255, 255, .24); }
.lb__close {
  position: absolute;
  top: clamp(12px, 3vw, 28px);
  right: clamp(12px, 3vw, 28px);
  font-size: 20px;
}

/* ============================================================
   THE HAND POINTER
   Off unless js/app.js turns it on (fine pointer + user preference).
   To use a PNG instead: give .hand a background-image, hide .hand svg.
   ============================================================ */
.hand {
  position: fixed;
  top: 0; left: 0;
  z-index: 200;
  width: 46px;
  height: 46px;
  display: none;
  pointer-events: none;
  background: url(../assets/cursor.png) center / contain no-repeat;
  filter: drop-shadow(0 3px 5px rgba(15, 45, 65, .45));
  transform: translate3d(-200px, -200px, 0);
  will-change: transform;
}
html.hand-on .hand { display: block; }
html.hand-on, html.hand-on * { cursor: none !important; }

/* ---------- the open-channel bloom ---------- */
.flash {
  position: fixed;
  inset: 0;
  z-index: 150;
  pointer-events: none;
  background: radial-gradient(60% 50% at 50% 45%, #ffffff 0%, rgba(255, 255, 255, .55) 55%, rgba(255, 255, 255, 0) 100%);
  opacity: 0;
}
.flash.is-firing { animation: bloom 420ms cubic-bezier(.2, .7, .3, 1) both; }
@keyframes bloom {
  0%   { opacity: 0; }
  22%  { opacity: .72; }
  100% { opacity: 0; }
}
html.reduce-motion .flash { animation: none !important; opacity: 0 !important; }
