/* ==========================================================================
 * Hero · the Nova Orrery: Nova Room inside a 24-hour day ring.
 * --------------------------------------------------------------------------
 * The stage (poster, canvas, projected labels) and the panel under it (the
 * two keys, the status line, the caption). Driven by js/orrery/hero.js; the
 * hero grid itself lives in home.css. The canvas is transparent: the night
 * and the moonlight glow behind it are the page's.
 * ========================================================================== */

.orrery {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
}

/* ---- Stage ---------------------------------------------------------------- */
.orrery__stage {
  position: relative;
  width: min(620px, 46vw);
  aspect-ratio: 1;
  /* Horizontal drags spin the instrument; vertical ones and pinch-zoom stay
   * the page's. */
  touch-action: pan-y pinch-zoom;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
/* Below the two-column layout the stage runs edge to edge: the ring needs
 * the width more than the page needs its gutter. */
@media (max-width: 939px) {
  .orrery__stage {
    width: min(100vw, 600px);
    margin-inline: calc((100% - min(100vw, 600px)) / 2);
  }
}
.orrery.is-live .orrery__stage { cursor: grab; }
.orrery.is-live .orrery__stage.is-over-key { cursor: pointer; }
.orrery.is-live .orrery__stage.is-dragging { cursor: grabbing; }

.orrery__poster,
.orrery__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.orrery__poster { pointer-events: none; -webkit-user-drag: none; }
.orrery__canvas { opacity: 0; }
/* The poster is a render of the canvas's first frame: a pristine page swaps
 * in one go (a crossfade between two identical half-transparent images would
 * dim them on the way). After a press, or in another accent, they differ, and
 * hero.js asks for the crossfade. */
.orrery.is-live .orrery__canvas { opacity: 1; }
.orrery.is-live .orrery__poster { opacity: 0; }
.orrery.is-crossfade .orrery__canvas,
.orrery.is-crossfade .orrery__poster { transition: opacity 0.5s var(--ease-out, ease-out); }

/* ---- Labels: micro type projected from the ring each frame -------------- */
.orrery__labels {
  position: absolute;
  inset: 0;
  pointer-events: none;
  contain: layout style;
}
.orrery__label {
  position: absolute;
  left: 0;
  top: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 0.55em;
  padding: 2px 0;
  white-space: nowrap;
  font-size: 10.5px;
  line-height: 1.2;
  font-weight: 650;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  color: var(--text-2);
  opacity: 0;
  transition: opacity 0.28s var(--ease-out, ease-out);
  will-change: transform, opacity;
}
.orrery__label.is-on { opacity: 1; }
.orrery__label-v {
  letter-spacing: 0.04em;
  color: color-mix(in srgb, var(--text-1) 86%, transparent);
}
.orrery__label--next,
.orrery__label--next .orrery__label-v { color: var(--accent-bright); }
.orrery__label--nap,
.orrery__label--nap .orrery__label-v { color: var(--accent-bright); }
.orrery__label--nap .orrery__label-v { text-transform: none; letter-spacing: 0.02em; }
.orrery__label--hour {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
}
.orrery__label--hour .orrery__label-v { color: var(--text-2); } /* --muted dips under 4.5:1 over the glow */

/* ---- Panel ------------------------------------------------------------------ */
.orrery__panel {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: 14px;
  width: min(100%, 520px);
  /* The bottom of the stage is open sky; the panel tucks into it (hero.js
   * keeps the labels above the panel's top edge). */
  margin-top: calc(min(620px, 46vw) * -0.24);
  text-align: center;
}
@media (max-width: 939px) {
  .orrery__panel { margin-top: calc(min(100vw, 600px) * -0.22); }
}

/* The two keys, built like the device's: two ivory halves of one capsule,
 * split by a slot where the red LED sits. They do nothing without JS, so the
 * markup ships them hidden and hero.js shows them; until then they keep
 * their room, so nothing moves when they appear. */
.orrery__keys[hidden] { display: grid !important; visibility: hidden; }
.orrery__status[hidden] { display: block !important; visibility: hidden; }
.orrery__keys {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  width: min(100%, 360px);
  padding: 4px;
  border-radius: 999px;
  background: linear-gradient(180deg, #cfc6b5 0%, #bdb3a1 100%);
  box-shadow:
    inset 0 1px 2px rgba(22, 19, 15, 0.45),
    0 0 0 1px rgba(255, 255, 255, 0.05),
    0 22px 48px -22px rgba(0, 0, 0, 0.9),
    0 0 60px -20px color-mix(in srgb, var(--accent) 40%, transparent);
}
.key {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 52px;
  padding: 0 16px;
  color: var(--ivory-ink, #16130f);
  background: linear-gradient(180deg, #f6f1e7 0%, #e7dfcf 100%);
  font-size: 15px;
  font-weight: 650;
  letter-spacing: -0.005em;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -2px 3px rgba(110, 88, 56, 0.16),
    0 1px 1px rgba(22, 19, 15, 0.3);
  transition:
    transform 0.12s var(--ease-out, ease-out),
    box-shadow 0.12s var(--ease-out, ease-out),
    background 0.2s var(--ease-out, ease-out);
}
.key--moon { border-radius: 999px 8px 8px 999px; }
.key--sun { border-radius: 8px 999px 999px 8px; }
.key:hover { background: linear-gradient(180deg, #faf6ee 0%, #ece5d6 100%); }
.key:active {
  transform: translateY(1px);
  box-shadow:
    inset 0 2px 5px rgba(80, 60, 30, 0.28),
    0 0 0 rgba(22, 19, 15, 0);
}
.key:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 4px;
  border-radius: 999px 8px 8px 999px;
}
.key--sun:focus-visible { border-radius: 8px 999px 999px 8px; }
/* Asleep: the moon stays down until the sun is pressed, with a ring in the
 * accent (over 3:1 on the ivory) so the state never rests on a shade alone. */
.key[aria-pressed="true"] {
  background: linear-gradient(180deg, #d9cfbc 0%, #e6ddcc 100%);
  box-shadow:
    inset 0 2px 6px rgba(80, 60, 30, 0.38),
    inset 0 0 0 2px color-mix(in srgb, var(--accent) 62%, #1c1830);
}
.key__icon {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  color: #3d362f;
}
.key[aria-pressed="true"] .key__icon { color: color-mix(in srgb, var(--accent) 62%, #1c1830); }
.key__label { white-space: nowrap; }

.key-led {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: #6d2a22;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}
/* One dim blink for the moon, two for the sun: what Nova Room does. */
.key-led.is-blink-1 { animation: key-led 0.42s linear 1; }
.key-led.is-blink-2 { animation: key-led 0.32s linear 2; }
@keyframes key-led {
  0%, 52% {
    background: var(--led, #ff4a36);
    box-shadow: 0 0 8px 2px rgba(255, 74, 54, 0.55), 0 0 2px 1px rgba(255, 140, 120, 0.8);
  }
  60%, 100% { background: #6d2a22; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.4); }
}

.orrery__status {
  max-width: 34em;
  min-height: 3.1em; /* two lines: the longest message at this width */
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-2);
  text-wrap: balance;
}
.orrery__status strong { color: var(--text-1); font-weight: 650; white-space: nowrap; }
.orrery__status-line { display: block; }
.orrery__status-line--next { color: var(--text-2); } /* quieter by weight, not by contrast */
/* The demo changes this line without anyone touching the page, so it holds
 * the room its longest message needs (measured at each width) and the page
 * below never jumps. */
@media (min-width: 940px) and (max-width: 1023px) {
  .orrery__status { min-height: 4.65em; } /* the narrowest two-column layout */
}
@media (max-width: 519px) {
  .orrery__status { font-size: 14px; min-height: 4.65em; }
}
@media (max-width: 379px) {
  .orrery__status { min-height: 6.2em; }
}
.orrery__caption {
  margin-top: -6px;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--text-2); /* --muted dips under 4.5:1 over the glow */
}

/* Pause motion (WCAG 2.2.2): small, but a full 44 px target. Pressed means
 * paused; its name never changes, its look does. Shipped hidden: hero.js
 * shows it where something could move by itself, and until then it keeps
 * its room. */
.orrery__still[hidden] { display: inline-flex !important; visibility: hidden; }
.orrery__still {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-top: -10px;
  padding: 0 16px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  transition:
    color 0.2s var(--ease-out, ease-out),
    background-color 0.2s var(--ease-out, ease-out),
    border-color 0.2s var(--ease-out, ease-out);
}
.orrery__still:hover { color: var(--text-1); border-color: color-mix(in srgb, var(--text-2) 45%, transparent); }
.orrery__still:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: 3px; border-radius: 999px; }
.orrery__still[aria-pressed="true"] {
  color: var(--text-1);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-color: color-mix(in srgb, var(--accent-bright) 55%, transparent);
}
.orrery__still[aria-pressed="true"] .orrery__still-icon { color: var(--accent-bright); }
/* "Drag to spin" only once there is something to spin. */
.orrery__caption-live { display: none; }
.orrery.is-live .orrery__caption-live { display: inline; }

@media (prefers-reduced-motion: reduce) {
  .key { transition: none; }
  .orrery__label { transition: none; }
  .orrery__still { transition: none; }
}

/* Forced colours drop the ivory capsule and the pressed shading: draw the
 * keys as buttons and fill the pressed ones with the system highlight (the
 * outline stays free for the focus ring). */
@media (forced-colors: active) {
  .orrery__keys { border: 1px solid CanvasText; }
  .key { border: 2px solid ButtonText; background: ButtonFace; color: ButtonText; transition: none; }
  /* Own system colours, no adjusting: otherwise the browser's text backplate
   * covers the label on the highlight. */
  .key[aria-pressed="true"],
  .orrery__still[aria-pressed="true"] {
    forced-color-adjust: none;
    background: Highlight;
    color: HighlightText;
    border-color: Highlight;
  }
  .orrery__still { transition: none; }
  .key .key__icon,
  .key[aria-pressed="true"] .key__icon,
  .orrery__still[aria-pressed="true"] .orrery__still-icon { color: inherit; }
  .key-led { forced-color-adjust: none; }
}
