/* lon3ly.cloud — the sky is the content; the UI is furniture */

@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --accent: rgba(190, 205, 235, 0.9);
  /* These six are re-written from JS as the sky brightens, so white furniture
     never ends up on a white overcast. Values here are the dark-sky end. */
  --glass-bg: rgba(255, 255, 255, 0.08);
  --glass-border: rgba(255, 255, 255, 0.14);
  --glass-highlight: rgba(255, 255, 255, 0.12);
  --panel-bg: rgba(14, 20, 34, 0.82);
  --ink: rgba(240, 244, 252, 0.92);
  --ink-dim: rgba(240, 244, 252, 0.55);
  --meta-shadow: rgba(4, 8, 20, 0.5);
  /* the embossed-glass digits, likewise */
  --clk-1: rgba(255, 255, 255, 0.92);
  --clk-2: rgba(238, 245, 253, 0.48);
  --clk-3: rgba(198, 214, 238, 0.30);
  --clk-4: rgba(255, 255, 255, 0.58);
  --clk-rim-hi: rgba(255, 255, 255, 0.5);
  --clk-rim-lo: rgba(8, 14, 30, 0.45);
  --clk-drop: rgba(4, 8, 20, 0.42);
  --clk-halo: rgba(228, 238, 252, 0.15);
  --radius-panel: 18px;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  --ease-soft: cubic-bezier(0.4, 0.0, 0.2, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  height: 100%;
  overflow: hidden;
  background: #060a14;
  font-family: var(--font-ui);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

/* ---------- Sky layers ---------- */
canvas#skyBase, canvas#skyStars, canvas#skyClouds, canvas#skyPrecip, canvas#clockClouds {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
#skyBase   { z-index: 0; }
#skyStars  { z-index: 1; transition: opacity 1.2s var(--ease-soft); }
#skyClouds { z-index: 2; }
#skyPrecip { z-index: 3; pointer-events: none; }

#lightningFlash {
  position: fixed;
  inset: 0;
  background: #fff;
  opacity: 0;
  pointer-events: none;
  z-index: 4;
}

/* ---------- Boot curtain ----------
   The page opens pure black. The sky is revealed only once the real location and
   its weather have landed, then the furniture, then the clock — so nothing is
   ever seen in the wrong place, the wrong palette, or the wrong time. */
#boot {
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 60;
  pointer-events: none;
  opacity: 1;
  transition: opacity 1s var(--ease-soft);
}
#boot.gone { opacity: 0; }

/* the furniture waits for the sky */
#searchWrap, #controls {
  opacity: 0;
  transition: opacity 0.8s var(--ease-soft);
}
body.ui-in #searchWrap, body.ui-in #controls { opacity: 1; }

/* ---------- Glass ---------- */
.glass {
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(14px) saturate(1.25);
  backdrop-filter: blur(14px) saturate(1.25);
  border: 1px solid var(--glass-border);
  box-shadow:
    inset 0 1px 0 var(--glass-highlight),
    0 8px 28px rgba(4, 8, 20, 0.22);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: rgba(16, 22, 38, 0.62); }
}


/* ---------- Search (top-left) ---------- */
#searchWrap {
  position: fixed;
  top: max(16px, env(safe-area-inset-top));
  left: max(16px, env(safe-area-inset-left));
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 16px;
  height: 44px;
  min-width: 220px;
  max-width: min(420px, calc(100vw - 32px));
  border-radius: 999px;
}
#searchIcon { width: 17px; height: 17px; flex: none; color: var(--ink-dim); }
#searchInput {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  outline: none;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 15px;
  letter-spacing: 0.01em;
}
#searchInput::placeholder { color: var(--ink-dim); }

#searchResults {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  border-radius: var(--radius-panel);
  padding: 6px;
  display: flex;
  flex-direction: column;
}
#searchResults button {
  background: none;
  border: none;
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 14px;
  text-align: left;
  padding: 10px 12px;
  border-radius: 12px;
  cursor: pointer;
}
#searchResults button:hover,
#searchResults button.active { background: rgba(255, 255, 255, 0.09); }
#searchResults button small { color: var(--ink-dim); display: block; font-size: 11.5px; margin-top: 1px; }
/* the dropdown floats over an unpredictable sky, so it carries its own contrast
   rather than trusting the backdrop blur to do it */
#searchResults { background: var(--panel-bg); }
#searchResults button.special {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 8px;
}
#searchResults button.special svg { width: 14px; height: 14px; flex: none; }

/* ---------- Controls (bottom-right) ---------- */
#controls {
  position: fixed;
  right: max(16px, env(safe-area-inset-right));
  bottom: max(16px, env(safe-area-inset-bottom));
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 10px;
}
.ctl {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  color: var(--ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform 0.35s var(--ease-soft), background 0.35s var(--ease-soft), color 0.35s var(--ease-soft), opacity 0.35s var(--ease-soft);
  -webkit-tap-highlight-color: transparent;
}
.ctl svg { width: 20px; height: 20px; }
.ctl:hover { transform: translateY(-2px); background: rgba(255, 255, 255, 0.13); }
.ctl:active { transform: translateY(0) scale(0.96); }
.ctl:disabled { opacity: 0.35; cursor: default; transform: none; }
/* "on" has to be unmistakable against any sky, so it gets a ring as well as a
   tint — colour alone disappeared against a dark one */
.ctl.active {
  color: var(--accent);
  background: rgba(255, 255, 255, 0.18);
  box-shadow:
    inset 0 0 0 1.5px var(--accent),
    inset 0 1px 0 var(--glass-highlight),
    0 0 16px -4px var(--accent);
}

/* ambient on: the sound bars breathe slowly */
#btnAmbient.active svg path {
  transform-box: fill-box;
  transform-origin: center;
  animation: eqBreathe 3.2s var(--ease-soft) infinite;
}
#btnAmbient.active svg path:nth-child(1) { animation-delay: -0.4s; }
#btnAmbient.active svg path:nth-child(2) { animation-delay: -1.3s; animation-duration: 3.8s; }
#btnAmbient.active svg path:nth-child(3) { animation-delay: -2.1s; animation-duration: 3.5s; }
#btnAmbient.active svg path:nth-child(4) { animation-delay: -0.9s; animation-duration: 4.1s; }
#btnAmbient.active svg path:nth-child(5) { animation-delay: -1.7s; }
@keyframes eqBreathe {
  0%, 100% { transform: scaleY(1); }
  50% { transform: scaleY(0.42); }
}

/* teapot active: a warm hearth-glow */
#btnTeapot.active {
  color: #ffd9a6;
  background: rgba(255, 200, 130, 0.13);
  border-color: rgba(255, 205, 140, 0.38);
  box-shadow:
    0 0 22px rgba(255, 190, 110, 0.45),
    inset 0 1px 0 var(--glass-highlight);
}

/* sleep countdown replaces the moon while armed */
.sleepCount {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}

#radioWidget {
  display: flex;
  align-items: center;
  border-radius: 999px;
  padding: 0 4px;
  position: relative;
}
.ctl.bare {
  background: none;
  border: none;
  box-shadow: none;
  width: 40px;
  height: 44px;
}
.ctl.bare:hover { background: rgba(255, 255, 255, 0.09); transform: none; }

/* Tuning in: a stream can take several seconds to hand over its first samples, so
   the button says so rather than pretending it is already playing. */
#btnRadioPlay { position: relative; }
#btnRadioPlay.connecting svg { opacity: 0; }
#btnRadioPlay.connecting::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  border-top-color: transparent;
  animation: tuneIn 0.75s linear infinite;
}
@keyframes tuneIn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  #btnRadioPlay.connecting::after {
    animation: tunePulse 1.4s var(--ease-soft) infinite;
    border-top-color: var(--accent);
  }
  @keyframes tunePulse { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }
}

#volPopover {
  position: absolute;
  bottom: calc(100% + 10px);
  right: 0;
  border-radius: 999px;
  padding: 10px 14px;
}
#volSlider {
  width: 110px;
  accent-color: var(--accent);
  cursor: pointer;
}

#stationName {
  position: absolute;
  bottom: calc(100% + 10px);
  right: 0;
  transition: bottom 0.3s var(--ease-soft);
  white-space: nowrap;
  font-size: 12px;
  color: var(--ink-dim);
  letter-spacing: 0.02em;
  padding: 6px 2px;
  pointer-events: none;
}
/* the volume popover and the station name share the space above the radio widget —
   move the name up out of the way rather than letting them sit on top of each other */
#radioWidget:has(#volPopover:not([hidden])) #stationName { bottom: calc(100% + 58px); }

/* ---------- Sleep picker ---------- */
#sleepPicker {
  position: fixed;
  right: max(16px, env(safe-area-inset-right));
  bottom: calc(max(16px, env(safe-area-inset-bottom)) + 58px);
  z-index: 21;
  border-radius: 999px;
  padding: 6px 10px;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--ink-dim);
}
#sleepPicker button {
  background: none;
  border: none;
  color: var(--ink);
  font-size: 14px;
  font-family: var(--font-ui);
  padding: 8px 10px;
  border-radius: 999px;
  cursor: pointer;
  min-width: 44px;
  min-height: 36px;
}
#sleepPicker button:hover { background: rgba(255, 255, 255, 0.1); }

/* ---------- Tooltip ---------- */
#tooltip {
  position: fixed;
  z-index: 30;
  padding: 7px 12px;
  border-radius: 10px;
  font-size: 12.5px;
  color: var(--ink);
  letter-spacing: 0.01em;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.3s var(--ease-soft), transform 0.3s var(--ease-soft);
  white-space: nowrap;
}
#tooltip.show { opacity: 1; transform: translateY(0); }

/* ---------- Clock ---------- */
#clockOverlay {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2vh;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s var(--ease-soft);
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
#clockOverlay.open { opacity: 1; pointer-events: auto; }

#clockClouds {
  z-index: 11;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.9s var(--ease-soft);
}
#clockClouds.open { opacity: 1; }

/* The time and the poem occupy the same place and cross-fade between each other:
   the digits fade out, then the words fade in. Nothing in this overlay appears by
   simply being switched on. */
#clockTime, #clockPoem, #clockMeta {
  opacity: 0;
  transition: opacity 0.5s var(--ease-soft);
}
#clockTime.in, #clockPoem.in, #clockMeta.in { opacity: 1; }

#clockTime {
  position: relative;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(96px, 22vw, 320px);
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* Embossed glass slab: frosted gradient fill, a tight rim top and bottom, and
     one soft drop for depth. The rim shadows are deliberately 1px with no blur —
     an emboss is a hard edge catching light. Blurring them is what made the
     digits read as out of focus. */
  background: linear-gradient(
    180deg,
    var(--clk-1) 0%,
    var(--clk-2) 38%,
    var(--clk-3) 62%,
    var(--clk-4) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  text-shadow:
    0 1px 0 var(--clk-rim-lo),
    0 -1px 0 var(--clk-rim-hi),
    0 12px 34px var(--clk-drop);
  user-select: none;
}
/* One word, as large as the screen will take. Sized off both axes so it fills the
   width on a wide screen without overflowing the height on a short one. */
#clockTime.shout {
  font-size: min(23vw, 42vh);
  letter-spacing: -0.03em;
}
#clockTime.shout::before { inset: -60px; padding: 60px; }

/* the glass surround: a blurred twin of the digits, sitting behind them. Kept
   deliberately faint and tight — at 30px and a quarter opacity it bled light
   back into the glyph interiors and fogged the whole clock. */
#clockTime::before {
  content: attr(data-text);
  position: absolute;
  inset: -50px;
  padding: 50px;
  z-index: -1;
  color: var(--clk-halo);
  -webkit-text-fill-color: var(--clk-halo); /* else the parent's transparent fill inherits */
  filter: blur(15px);
  pointer-events: none;
}
/* the poem — the same glass as the digits, at reading size. Weighted to match
   the clock rather than whisper underneath it. */
#clockPoem {
  font-family: var(--font-display);
  font-weight: 600;
  /* Two lines, as written — one per line of the couplet. The size is tied to the
     viewport rather than clamped so the longest line always fits on one line
     instead of wrapping into four. */
  font-size: min(2.9vw, 42px);
  line-height: 1.45;
  letter-spacing: -0.005em;
  text-align: center;
  max-width: 96vw;
  user-select: none;
}
/* The glass is applied per line, not across the block: one gradient spanning both
   lines left the second one faded to nearly nothing. */
#clockPoem div {
  margin-bottom: 0.5em;
  white-space: nowrap;
  background: linear-gradient(
    180deg,
    var(--clk-1) 0%,
    var(--clk-2) 55%,
    var(--clk-4) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  text-shadow:
    0 1px 0 var(--clk-rim-lo),
    0 10px 30px var(--clk-drop);
}
#clockPoem div:last-child { margin-bottom: 0; }

#clockMeta {
  display: flex;
  gap: 14px;
  align-items: baseline;
  font-family: var(--font-display);
  font-weight: 300;
  color: var(--ink-dim);
  font-size: clamp(14px, 1.8vw, 19px);
  letter-spacing: 0.06em;
  text-shadow: 0 2px 14px var(--meta-shadow);
}
#clockPlace { color: var(--ink); font-weight: 500; }

/* ---------- Responsive ---------- */
/* bigger furniture on bigger rooms */
@media (min-width: 1200px) {
  .ctl { width: 52px; height: 52px; }
  .ctl.bare { width: 46px; height: 52px; }
  .ctl svg { width: 23px; height: 23px; }
  #controls { gap: 12px; }
  #tooltip { font-size: 13.5px; }
}
@media (min-width: 2000px) {
  .ctl { width: 60px; height: 60px; }
  .ctl.bare { width: 52px; height: 60px; }
  .ctl svg { width: 26px; height: 26px; }
  #controls { gap: 14px; }
}

@media (max-width: 600px) {
  /* The search pill is the one thing you have to hit accurately, so it spans the
     screen and gets real height. The input stays at 16px or more because anything
     smaller makes iOS zoom the whole page when you focus it. */
  #searchWrap {
    min-width: 0;
    width: auto;
    max-width: none;
    left: max(12px, env(safe-area-inset-left));
    right: max(12px, env(safe-area-inset-right));
    height: 54px;
    padding: 0 18px;
    gap: 10px;
  }
  #searchIcon { width: 19px; height: 19px; }
  #searchInput { font-size: 16.5px; }
  #searchResults button { padding: 13px 14px; font-size: 15px; }
  #searchResults button small { font-size: 12.5px; }

  /* The control row spans the full width and every pill shares it evenly, so the
     targets are as large as the screen allows instead of huddling in the corner. */
  #controls {
    left: max(12px, env(safe-area-inset-left));
    right: max(12px, env(safe-area-inset-right));
    gap: 8px;
  }
  .ctl {
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    height: 54px;
  }
  /* The radio widget holds three buttons, so it claims proportionally more room.
     Seven targets at the full 44px will not fit across a narrow phone — this
     weighting gets the three tightest ones as close to it as the width allows. */
  #radioWidget { flex: 2.8 1 0; min-width: 0; padding: 0; }
  .ctl.bare { flex: 1 1 0; width: auto; height: 54px; }
  .ctl:hover { transform: none; } /* no hover lift on a touch screen */

  #clockTime { font-size: clamp(72px, 21vw, 200px); white-space: nowrap; }
}
@media (max-width: 420px) {
  #controls { gap: 6px; }
  .ctl svg { width: 20px; height: 20px; }
  #searchWrap { height: 52px; padding: 0 16px; }
}
