/* Alight.
 *
 * The visual brief, in one sentence: it should feel like standing outside at
 * dusk — a lot of sky, very little furniture, and nothing asking for your
 * attention.
 *
 * Constraints that follow from the project's values, not from taste:
 *  · No web fonts. A font request is ~40KB and a third party learning that
 *    you opened a spiritual app at 3am. The system stack is beautiful and free.
 *  · No framework. The whole UI is smaller than a React runtime.
 *  · Motion is slow and optional. `prefers-reduced-motion` is honoured
 *    everywhere, and the ambient field stops entirely when the tab is hidden.
 *  · Dark by default, because this app is used at night, and light when the
 *    system asks for it.
 */

:root {
  --ink: #e8e4f0;
  --ink-soft: #a9a3be;
  --ink-faint: #6d6883;
  --bg: #0b0a12;
  --bg-raised: rgba(255, 255, 255, 0.035);
  --line: rgba(255, 255, 255, 0.08);
  --glow: #ffd9a0;
  --glow-soft: rgba(255, 217, 160, 0.16);
  /* How strongly the ambient field shows. On a dark page the motes read as
   * starlight; at the same opacity on a cream page they read as specks of
   * dirt drifting over the text. Same canvas, same colour, opposite meaning —
   * so the theme sets this and field.js obeys it. */
  --mote-alpha: 1;
  --accent: #8ec7d2;
  --accent-warm: #e0a3b8;
  --radius: 18px;
  --measure: 34rem;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  --font: ui-rounded, "SF Pro Rounded", -apple-system, BlinkMacSystemFont,
          "Segoe UI", system-ui, sans-serif;
  --font-quote: ui-serif, Georgia, "Iowan Old Style", "Palatino Linotype", serif;
}

:root[data-theme="light"] {
  --ink: #2a2436; --ink-soft: #5d5670; --ink-faint: #8b849c;
  --bg: #f6f2ec; --bg-raised: rgba(0, 0, 0, 0.025);
  --line: rgba(0, 0, 0, 0.08);
  --glow: #c08a3e; --glow-soft: rgba(192, 138, 62, 0.14);
  --accent: #3c7f8c; --accent-warm: #a8607a;
  --mote-alpha: 0.3;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --ink: #2a2436; --ink-soft: #5d5670; --ink-faint: #8b849c;
    --bg: #f6f2ec; --bg-raised: rgba(0, 0, 0, 0.025);
    --line: rgba(0, 0, 0, 0.08);
    --glow: #c08a3e; --glow-soft: rgba(192, 138, 62, 0.14);
    --accent: #3c7f8c; --accent-warm: #a8607a;
    --mote-alpha: 0.3;
  }
}

/* --- the grove ----------------------------------------------------------
 *
 * A second skin: warm wood, paper, bamboo and lantern light instead of deep
 * space. It exists for a reason beyond prettiness — a dark cosmos full of
 * planetary glyphs is an intimidating front door for someone wary of
 * astrology, and this app is meant to be a friend to people who did not come
 * for a star chart.
 *
 * Everything below is the same variables with different values, which is why
 * it costs almost nothing: the canvas field, the chart wheel and every card
 * read their colours from CSS and simply follow.
 */
:root[data-skin="grove"] {
  --ink: #33291f;
  --ink-soft: #6a5a48;
  --ink-faint: #97866f;
  --bg: #efe6d4;
  --bg-raised: rgba(120, 92, 56, 0.06);
  --line: rgba(90, 68, 40, 0.16);
  --glow: #c1832f;
  --glow-soft: rgba(193, 131, 47, 0.16);
  --accent: #5f8a5a;
  --accent-warm: #bd6f4e;
  --mote-alpha: 0.5;
}

/* Dusk in the grove, for dark mode and for night. Still wood and leaf, just
 * after the sun has gone. */
@media (prefers-color-scheme: dark) {
  :root[data-skin="grove"]:not([data-theme="light"]) {
    --ink: #eadfc9;
    --ink-soft: #b3a189;
    --ink-faint: #806f5b;
    --bg: #1c1811;
    --bg-raised: rgba(233, 214, 173, 0.05);
    --line: rgba(233, 214, 173, 0.10);
    --glow: #e5ad5c;
    --glow-soft: rgba(229, 173, 92, 0.15);
    --accent: #8fb07f;
    --accent-warm: #d38f68;
    --mote-alpha: 0.85;
  }
}
:root[data-skin="grove"][data-theme="dark"] {
  --ink: #eadfc9;
  --ink-soft: #b3a189;
  --ink-faint: #806f5b;
  --bg: #1c1811;
  --bg-raised: rgba(233, 214, 173, 0.05);
  --line: rgba(233, 214, 173, 0.10);
  --glow: #e5ad5c;
  --glow-soft: rgba(229, 173, 92, 0.15);
  --accent: #8fb07f;
  --accent-warm: #d38f68;
  --mote-alpha: 0.85;
}

/* Paper rather than a flat wash. Two very soft radial washes, no image, no
 * bytes — it reads as light falling through leaves onto a page. */
:root[data-skin="grove"] body {
  background-image:
    radial-gradient(ellipse 80% 55% at 12% 0%, rgba(160, 190, 140, 0.14), transparent 70%),
    radial-gradient(ellipse 70% 50% at 92% 22%, rgba(214, 160, 86, 0.13), transparent 72%);
  background-attachment: fixed;
}

/* Cards become paper cards: a hair more substantial, softer corners. */
:root[data-skin="grove"] .card { border-radius: 16px; }
:root[data-skin="grove"] blockquote,
:root[data-skin="grove"] .song { color: var(--ink); }

/* Grove furniture. Present only in the grove, and never in the way: it sits
 * behind everything, ignores pointer events, and is quiet enough that the
 * words always win. */
#grove { display: none; }
:root[data-skin="grove"] #grove {
  display: block; position: fixed; inset: 0; z-index: 0; pointer-events: none;
}
#grove-bamboo {
  position: absolute; left: 0; top: 0; height: 100%; width: 120px;
  opacity: 0.38;
}
#grove-bamboo .stalk rect { fill: #6f8f5c; }
#grove-bamboo .thin rect { fill: #86a36e; }
#grove-bamboo .leaf ellipse { fill: #5f8a5a; opacity: 0.75; }

#grove-panda {
  position: absolute; right: 3vw; bottom: 14px;
  width: clamp(116px, 15vw, 190px); height: auto;
  opacity: 0.66;
}
#grove-panda .light { fill: #faf3e4; }
#grove-panda .dark { fill: #3b352e; }
#grove-panda .eye { fill: #faf3e4; }
#grove-panda .mouth { fill: none; stroke: #3b352e; stroke-width: 2.4; stroke-linecap: round; }
#grove-panda .shoot rect { fill: #6f8f5c; }
#grove-panda .shoot ellipse { fill: #5f8a5a; }

/* At dusk the panda needs different values, not just less opacity. His white
 * goes luminous against a dark page and his black vanishes into it, which
 * leaves a floating pale blob with no face. Dimming the light parts and
 * lifting the dark ones keeps him legible as a panda. */
@media (prefers-color-scheme: dark) {
  :root[data-skin="grove"]:not([data-theme="light"]) #grove-bamboo { opacity: 0.26; }
  :root[data-skin="grove"]:not([data-theme="light"]) #grove-panda { opacity: 0.62; }
  :root[data-skin="grove"]:not([data-theme="light"]) #grove-panda .light,
  :root[data-skin="grove"]:not([data-theme="light"]) #grove-panda .eye { fill: #c9bda4; }
  :root[data-skin="grove"]:not([data-theme="light"]) #grove-panda .dark { fill: #6a5f4f; }
  :root[data-skin="grove"]:not([data-theme="light"]) #grove-panda .mouth { stroke: #6a5f4f; }
}
:root[data-skin="grove"][data-theme="dark"] #grove-panda .light,
:root[data-skin="grove"][data-theme="dark"] #grove-panda .eye { fill: #c9bda4; }
:root[data-skin="grove"][data-theme="dark"] #grove-panda .dark { fill: #6a5f4f; }
:root[data-skin="grove"][data-theme="dark"] #grove-panda .mouth { stroke: #6a5f4f; }

/* On a phone the bamboo would crowd the text, and the panda is nicer than the
 * stalks anyway. */
@media (max-width: 760px) {
  #grove-bamboo { opacity: 0.2; width: 74px; }
}
@media (max-width: 560px) {
  #grove-bamboo { display: none; }
  #grove-panda { opacity: 0.48; width: 106px; right: 2vw; }
}

/* The skin picker sits with the other quiet controls on the threshold. */
.skins { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 1.4em; }
.skins button { padding: 0.45em 1.05em; font-size: 0.92rem; color: var(--ink-soft); }
.skins button[aria-pressed="true"] {
  background: var(--glow-soft); border-color: var(--glow); color: var(--ink);
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0; min-height: 100%;
  background: var(--bg); color: var(--ink);
  font-family: var(--font);
  font-size: 17px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

#field { position: fixed; inset: 0; z-index: 0; pointer-events: none; }

main {
  position: relative; z-index: 1;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 12vh 16px 18vh;
}

h1 {
  font-size: clamp(2.4rem, 9vw, 3.4rem);
  font-weight: 300; letter-spacing: 0.06em;
  margin: 0 0 0.2em; line-height: 1.1;
}
h2 { font-size: 1.15rem; font-weight: 500; letter-spacing: 0.02em; margin: 0 0 0.6em; }

.lede { color: var(--ink-soft); font-size: 1.05rem; margin: 0 0 2.4em; max-width: 30rem; }
.soft { color: var(--ink-soft); }
.faint { color: var(--ink-faint); font-size: 0.86rem; line-height: 1.55; }

/* --- the slow arrival of each view ------------------------------------- */
.view { animation: rise 900ms var(--ease) both; }
.view[hidden] { display: none; }
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* --- controls ---------------------------------------------------------- */
label { display: block; font-size: 0.82rem; letter-spacing: 0.08em;
        text-transform: uppercase; color: var(--ink-faint); margin: 1.6em 0 0.5em; }

input[type="date"], input[type="time"], input[type="text"], select {
  width: 100%; padding: 0.8em 0.95em;
  background: var(--bg-raised); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px;
  font: inherit; font-size: 1rem;
  transition: border-color 300ms var(--ease), background 300ms var(--ease);
}
input:focus-visible, select:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px;
}
input:hover, select:hover { border-color: rgba(142, 199, 210, 0.4); }

.row { display: flex; gap: 12px; }
.row > * { flex: 1; }

button {
  font: inherit; cursor: pointer;
  border-radius: 999px; border: 1px solid var(--line);
  background: var(--bg-raised); color: var(--ink);
  padding: 0.7em 1.4em;
  transition: transform 300ms var(--ease), background 300ms var(--ease),
              border-color 300ms var(--ease);
}
button:hover { transform: translateY(-1px); border-color: var(--glow-soft); }
button:active { transform: translateY(0); }

button.primary {
  background: linear-gradient(135deg, var(--glow-soft), transparent);
  border-color: var(--glow-soft);
  padding: 0.85em 2em; margin-top: 2.2em;
  letter-spacing: 0.04em;
}
/* The sound toggle sits under the primary action, quietly. It is on the first
 * screen rather than in a settings menu because turning sound OFF has to be
 * findable by someone who has just been startled by it. */
.sound-row { margin-top: 1.4em; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sound-row .faint { font-size: 0.8rem; }
#sound[aria-pressed="true"] { color: var(--glow); }

button.quiet {
  border-color: transparent; background: none;
  color: var(--ink-faint); padding-left: 0.4em;
}
button.quiet:hover { color: var(--ink); transform: none; border-color: transparent; }

.moods { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 0.4em; }
.moods button { padding: 0.5em 1.1em; font-size: 0.95rem; color: var(--ink-soft); }
.moods button[aria-pressed="true"] {
  background: var(--glow-soft); border-color: var(--glow); color: var(--ink);
}

/* --- the reading ------------------------------------------------------- */
.card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5em 1.6em;
  margin: 1.1em 0;
  animation: rise 900ms var(--ease) both;
}
.card h3 {
  font-size: 0.74rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--ink-faint);
  margin: 0 0 0.85em;
}
.card p:last-child { margin-bottom: 0; }

blockquote {
  margin: 0; font-family: var(--font-quote);
  font-size: 1.25rem; line-height: 1.5; font-style: italic;
  color: var(--ink);
}
.attribution { margin-top: 0.9em; font-size: 0.8rem; color: var(--ink-faint); font-style: normal; }

.song { font-family: var(--font-quote); font-size: 1.18rem; line-height: 1.75;
        white-space: pre-line; color: var(--glow); margin: 0; }

.action { font-size: 1.1rem; margin: 0; }

.confidence {
  display: inline-block; font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; padding: 0.25em 0.7em; border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink-faint); margin-left: 0.5em;
  vertical-align: 0.15em;
}

.unknowns { border-left: 2px solid var(--line); padding-left: 1em; margin: 2em 0; }

/* The aside is lighter than everything around it, on purpose. No heading, no
 * attribution, no border — it should read as a friend leaning over rather than
 * as another section of a document. */
.card.aside {
  background: none; border: none;
  padding: 0.4em 1.6em 0;
  font-family: var(--font-quote); font-size: 1.12rem;
  color: var(--accent);
}

/* The care view is deliberately the plainest thing in the app. */
.care { border-color: var(--accent-warm); background: rgba(224, 163, 184, 0.07); }
.care a { color: var(--accent); }
.care ul { list-style: none; padding: 0; margin: 1.2em 0 0; }
.care li { padding: 0.6em 0; border-top: 1px solid var(--line); }

/* --- the opening ------------------------------------------------------- */
#genesis {
  position: fixed; inset: 0; z-index: 5;
  background: var(--bg);
  display: flex; flex-direction: column;
  align-items: center; justify-content: flex-end;
  padding: 16px;
}
#genesis[hidden] { display: none; }
#genesis-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
/* The words sit low and the cosmos keeps the middle.
 *
 * The first version centred them, which put every sentence directly on top of
 * the densest part of the burst — legible in a still frame and not in motion.
 * A lower third is the film convention for exactly this reason: the event and
 * the caption should not compete for the same pixels. */
#genesis-scrim {
  position: absolute; left: 0; right: 0; bottom: 0; height: 58%;
  background: linear-gradient(to top,
    rgba(11,10,18,0.97) 0%, rgba(11,10,18,0.93) 34%,
    rgba(11,10,18,0.66) 62%, rgba(11,10,18,0) 100%);
  pointer-events: none;
}
#genesis-words {
  position: relative; z-index: 1;
  max-width: 30rem; text-align: center;
  padding: 0 1.2rem;
  margin-bottom: clamp(4.5rem, 12vh, 8rem);
  min-height: 11rem;
}
#genesis-title {
  font-size: clamp(1.4rem, 5vw, 2rem); font-weight: 300;
  line-height: 1.25; margin: 0 0 0.5em; color: var(--ink);
}
#genesis-body { font-size: 1.02rem; color: var(--ink-soft); margin: 0 0 1.1em; }
#genesis-truth { max-width: 26rem; margin: 0 auto; line-height: 1.6; }
#genesis-voice {
  font-family: var(--font-quote); font-style: italic;
  font-size: 1.12rem; line-height: 1.5; color: var(--glow);
  margin: 1.6em auto 0; max-width: 24rem;
}
#genesis-attribution { margin: 0.7em 0 0; }
#genesis-voice[hidden], #genesis-attribution[hidden] { display: none; }
#genesis-words p { animation: rise 1200ms var(--ease) both; }
#genesis-skip {
  position: absolute; z-index: 2;
  bottom: max(24px, env(safe-area-inset-bottom)); right: 24px;
}
/* The invitation onward.
 *
 * It appears only once the scene has finished moving, and then it waits — no
 * countdown, no progress bar, nothing that implies you are behind. It breathes
 * slowly so it can be noticed without demanding to be. */
#genesis-next {
  position: absolute; z-index: 2;
  bottom: max(24px, env(safe-area-inset-bottom)); left: 50%;
  transform: translateX(-50%);
  border-color: var(--glow-soft);
  animation: arrive 1600ms var(--ease) both, breathe 5s ease-in-out 1600ms infinite;
  letter-spacing: 0.06em;
}
#genesis-next:hover { transform: translateX(-50%) translateY(-1px); }
#genesis-next[hidden] { display: none; }
@keyframes arrive { from { opacity: 0; } to { opacity: 1; } }
@keyframes breathe { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
/* The opening is dark by nature. In light mode it stays dark rather than
 * washing out — it is the one screen that is meant to be night. */
:root[data-theme="light"] #genesis, :root:not([data-theme="dark"]) #genesis {
  background: #0b0a12;
}
:root[data-theme="light"] #genesis-title, :root:not([data-theme="dark"]) #genesis-title { color: #e8e4f0; }
:root[data-theme="light"] #genesis-body, :root:not([data-theme="dark"]) #genesis-body { color: #a9a3be; }
:root[data-theme="light"] #genesis-skip, :root:not([data-theme="dark"]) #genesis-skip { color: #a9a3be; }

/* --- breathing ---------------------------------------------------------- */
#breath-stage {
  position: relative;
  height: 15rem; margin: 2.5rem 0 1rem;
  display: flex; align-items: center; justify-content: center;
}
#breath-circle {
  position: absolute;
  width: 13rem; height: 13rem; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%,
    var(--glow-soft) 0%, rgba(255, 217, 160, 0.05) 60%, transparent 72%);
  border: 1px solid var(--glow-soft);
  /* No CSS transition. The size is driven frame by frame from the pure model
   * in core/breath.js, so a transition would fight it and lag the cue. */
  will-change: transform, opacity;
}
#breath-cue {
  position: relative; margin: 0;
  font-size: 1.15rem; letter-spacing: 0.22em;
  text-transform: lowercase; color: var(--ink-soft);
}
#breath-count { min-height: 1.4em; margin: 0 0 1.5em; }

#wheel { width: 100%; height: auto; display: block; margin: 0.5em 0; }

footer { margin-top: 5em; padding-top: 2em; border-top: 1px solid var(--line); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media (max-width: 480px) {
  main { padding: 8vh 16px 12vh; }
  .row { flex-direction: column; }
}
