/* ==========================================================================
   TYDE

   Two things earn their complexity here.

   The first is --v: a single 0..1 number, written to the root element once per
   animation frame, that every visual on the page derives from. The orbs scale
   from it, the chrome brightens from it, the canvases read it. One write per
   frame instead of a dozen, and nothing can drift out of phase with anything
   else because there is only one clock.

   The second is that the page has two shapes. Idle, the pattern editor is the
   hero, because the editable pattern is the whole idea. Running, the editor
   folds down to a strip and the ring takes the room — and after a while of not
   touching anything, the chrome fades out entirely. You came here to breathe,
   not to look at buttons.
   ========================================================================== */

:root{
  --teal:#3ad6c4;
  --lav:#9d8cff;
  --bg:#070b0f;
  --bg-2:#0b131b;
  --ink:#e9f2f3;
  --dim:#7e969b;
  --line:rgba(255,255,255,.10);
  --line-2:rgba(255,255,255,.18);
  --glass:rgba(255,255,255,.035);
  --glass-2:rgba(255,255,255,.07);
  --lift:0 24px 70px -30px rgba(0,0,0,.9);
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  --v:.25;                     /* the breath, 0..1 — written by app.js */
  --ease:cubic-bezier(.22,.61,.36,1);
}

:root[data-theme="day"]{
  --teal:#2f8f8a;
  --lav:#8b7fc7;
  --bg:#f3f0ea;
  --bg-2:#e6e1d7;
  --ink:#1b2a2e;
  --dim:#6b7d80;
  --line:rgba(27,42,46,.14);
  --line-2:rgba(27,42,46,.26);
  --glass:rgba(255,255,255,.58);
  --glass-2:rgba(255,255,255,.8);
  --lift:0 20px 50px -28px rgba(27,42,46,.45);
}

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

html{-webkit-text-size-adjust:100%}

body{
  min-height:100svh;
  background:
    radial-gradient(120% 80% at 50% -10%, var(--bg-2), transparent 62%),
    var(--bg);
  color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  -webkit-font-smoothing:antialiased;
  display:flex;flex-direction:column;
  overflow-x:hidden;
  transition:background .6s var(--ease),color .6s var(--ease);
}

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

/* the wordmark gradient follows the theme; presentation attributes can't read
   custom properties, so it's re-pointed here */
.mark stop:first-child{stop-color:var(--teal)}
.mark stop:last-child{stop-color:var(--lav)}

/* ---------- ambient ------------------------------------------------------ */

.aura{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.orb{
  position:absolute;border-radius:50%;
  filter:blur(70px);
  will-change:transform,opacity;
  transition:opacity .8s var(--ease);
}
.o1{
  left:50%;top:46%;width:min(74vw,860px);aspect-ratio:1;
  background:radial-gradient(circle at 42% 38%,color-mix(in srgb,var(--teal) 52%,transparent),transparent 66%);
  transform:translate(-50%,-50%) scale(calc(.62 + var(--v) * .46));
  opacity:calc(.34 + var(--v) * .30);
}
.o2{
  left:26%;top:64%;width:min(46vw,540px);aspect-ratio:1;
  background:radial-gradient(circle at 50% 50%,color-mix(in srgb,var(--lav) 46%,transparent),transparent 68%);
  transform:translate(-50%,-50%) scale(calc(.7 + var(--v) * .34));
  opacity:calc(.24 + var(--v) * .24);
  animation:drift1 34s ease-in-out infinite;
}
.o3{
  left:76%;top:34%;width:min(40vw,470px);aspect-ratio:1;
  background:radial-gradient(circle at 50% 50%,color-mix(in srgb,var(--teal) 40%,transparent),transparent 68%);
  transform:translate(-50%,-50%) scale(calc(.66 + var(--v) * .38));
  opacity:calc(.18 + var(--v) * .22);
  animation:drift2 44s ease-in-out infinite;
}
/* the same wash reads much fainter over paper than over ink */
:root[data-theme="day"] .o1{opacity:calc(.46 + var(--v) * .34)}
:root[data-theme="day"] .o2{opacity:calc(.38 + var(--v) * .28)}
:root[data-theme="day"] .o3{opacity:calc(.30 + var(--v) * .26)}

@keyframes drift1{
  0%,100%{margin:0 0}
  50%{margin:-4vh 5vw}
}
@keyframes drift2{
  0%,100%{margin:0 0}
  50%{margin:5vh -4vw}
}

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

/* film grain — 3.5% of an SVG turbulence, enough to kill gradient banding */
.grain{
  position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.vignette{
  position:fixed;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(115% 82% at 50% 42%,transparent 45%,rgba(0,0,0,.42));
  opacity:1;transition:opacity .6s var(--ease);
}
:root[data-theme="day"] .vignette{opacity:.16}
:root[data-theme="day"] .grain{opacity:.035;mix-blend-mode:multiply}

/* ---------- chrome ------------------------------------------------------- */

.top,.dock,.foot{position:relative;z-index:3;width:100%;max-width:1180px;margin:0 auto}

.top{
  display:flex;align-items:center;gap:.95rem;
  padding:1.9rem clamp(1rem,4vw,2rem) 0;
  transition:opacity .5s var(--ease);
}
.mark{width:38px;height:38px;flex:none;color:var(--ink)}
.wm h1{font-size:1.22rem;font-weight:600;letter-spacing:.36em;line-height:1;text-indent:.36em}
.wm p{margin-top:.34rem;font-family:var(--mono);font-size:.56rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--dim)}

.util{margin-left:auto;display:flex;align-items:center;gap:.5rem}
.privacy{font-family:var(--mono);font-size:.54rem;letter-spacing:.15em;text-transform:uppercase;
  color:var(--dim);opacity:.8;margin-right:.75rem}
.icon{
  width:34px;height:34px;display:grid;place-items:center;color:var(--dim);
  background:var(--glass);border:1px solid var(--line);border-radius:11px;
  cursor:pointer;transition:.22s var(--ease);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
}
.icon svg{width:18px;height:18px}
.icon:hover{color:var(--ink);border-color:var(--line-2);transform:translateY(-1px)}
.icon .i-day{display:none}
:root[data-theme="day"] .icon .i-day{display:block}
:root[data-theme="day"] .icon .i-night{display:none}

/* ---------- stage -------------------------------------------------------- */

.stage{
  position:relative;z-index:2;flex:1;
  min-height:clamp(230px,34vh,420px);
  display:grid;place-items:center;
  padding:1rem 1rem .4rem;
}
#ring{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}

.dial{position:relative;text-align:center;line-height:1;user-select:none}
.d-phase{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.3em;text-transform:uppercase;
  color:var(--dim);transition:color .4s var(--ease)
}
.d-count{
  margin:.55rem 0 .5rem;
  font-size:clamp(2.6rem,7vw,4.1rem);font-weight:200;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;
  color:var(--ink);
  text-shadow:0 0 calc(18px + var(--v) * 34px) color-mix(in srgb,var(--teal) 42%,transparent);
}
:root[data-theme="day"] .d-count{text-shadow:none}
.d-sub{font-family:var(--mono);font-size:.54rem;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);opacity:.8}

/* ---------- dock --------------------------------------------------------- */

.dock{
  margin-top:.4rem;
  padding:clamp(.9rem,2vw,1.3rem) clamp(.9rem,3vw,1.5rem);
  background:var(--glass);
  border:1px solid var(--line);
  border-radius:22px;
  box-shadow:var(--lift);
  -webkit-backdrop-filter:blur(26px) saturate(1.3);
  backdrop-filter:blur(26px) saturate(1.3);
  transition:opacity .5s var(--ease),transform .5s var(--ease),border-color .5s var(--ease);
  max-width:1180px;
}
@media(min-width:1240px){ .dock{margin-left:auto;margin-right:auto} }

.editor{position:relative;height:212px;transition:height .55s var(--ease)}
#curve{display:block;width:100%;height:100%;touch-action:none;cursor:default}
#curve.over{cursor:ew-resize}
#curve.drag{cursor:grabbing}

/* lives in the status line rather than over the canvas — a label that collides
   with the thing it describes isn't a hint */
.hint{color:var(--teal);opacity:.75;animation:pulse 3.6s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.4}50%{opacity:.85}}
.hint[hidden]{display:none}

.row{display:flex;align-items:center;gap:1.2rem;flex-wrap:wrap}
.row-tune{margin-top:.5rem;padding-top:.95rem;border-top:1px solid var(--line)}

/* four phase durations, adjustable without the mouse — the canvas is the fun
   way to edit a pattern, this is the reliable one */
.steppers{display:flex;gap:.45rem;flex-wrap:wrap}
.step{
  display:grid;grid-template-columns:auto auto auto;align-items:center;gap:.1rem;
  border:1px solid var(--line);border-radius:12px;padding:.28rem .3rem;background:var(--glass);
}
.step .lbl{
  grid-column:1/-1;text-align:center;font-family:var(--mono);font-size:.48rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dim);padding-bottom:.16rem
}
.step button{
  width:22px;height:24px;display:grid;place-items:center;
  background:none;border:none;color:var(--dim);cursor:pointer;border-radius:7px;
  font-size:.9rem;line-height:1;transition:.18s
}
.step button:hover{background:var(--glass-2);color:var(--ink)}
.step button:disabled{opacity:.25;cursor:default;background:none}
.step .val{
  min-width:2.5rem;text-align:center;font-family:var(--mono);font-size:.78rem;font-weight:600;
  color:var(--ink);font-variant-numeric:tabular-nums
}
.step[data-p="0"] .lbl{color:var(--teal)}
.step[data-p="2"] .lbl{color:var(--lav)}

.readout{margin-left:auto;display:flex;align-items:baseline;gap:1.9rem}
.ro{display:grid;gap:.24rem;text-align:right}
.ro b{font-size:1.4rem;font-weight:500;letter-spacing:-.02em;line-height:1;font-variant-numeric:tabular-nums}
.ro span{font-family:var(--mono);font-size:.5rem;letter-spacing:.15em;text-transform:uppercase;color:var(--dim)}

.note{
  margin-top:.85rem;font-size:.83rem;line-height:1.6;color:var(--dim);max-width:62ch;
  min-height:2.6em;
}

.row-play{margin-top:1rem;padding-top:1rem;border-top:1px solid var(--line)}

.presets{display:flex;gap:.35rem;flex-wrap:wrap}
.chip{
  font-family:var(--mono);font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);background:var(--glass);border:1px solid var(--line);
  border-radius:999px;padding:.42rem .78rem;cursor:pointer;transition:.2s var(--ease);white-space:nowrap
}
.chip:hover{border-color:var(--line-2);color:var(--ink)}
.chip.on{
  color:var(--ink);border-color:transparent;
  background:linear-gradient(100deg,color-mix(in srgb,var(--teal) 30%,transparent),color-mix(in srgb,var(--lav) 30%,transparent));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--teal) 40%,transparent)
}

.transport{margin-left:auto;display:flex;align-items:center;gap:.75rem;flex-wrap:wrap}
.sessions,.voices{display:flex;gap:.2rem;padding:.22rem;border:1px solid var(--line);border-radius:999px;background:var(--glass)}
.sess,.voice{
  font-family:var(--mono);font-size:.55rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--dim);background:none;border:none;border-radius:999px;padding:.3rem .58rem;cursor:pointer;transition:.18s
}
.sess:hover,.voice:hover{color:var(--ink)}
.sess.on{background:var(--glass-2);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}
/* the chosen voice carries the gradient — it's the one control that makes noise */
.voice.on{
  color:var(--ink);
  background:linear-gradient(100deg,color-mix(in srgb,var(--teal) 34%,transparent),color-mix(in srgb,var(--lav) 34%,transparent));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--teal) 45%,transparent)
}
.voice[data-v="off"].on{background:var(--glass-2);box-shadow:inset 0 0 0 1px var(--line);color:var(--dim)}

.sound{display:flex;align-items:center;gap:.5rem}
.sound .spk{width:15px;height:15px;flex:none;color:var(--teal);transition:.25s var(--ease)}
.sound.muted .spk{color:var(--dim);opacity:.5}
.sound.muted .spk .wv{opacity:.15}
.sound.muted input[type=range]{opacity:.25;pointer-events:none}
.ghost{
  display:inline-flex;align-items:center;gap:.42rem;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--dim);background:var(--glass);border:1px solid var(--line);border-radius:999px;
  padding:.44rem .74rem;cursor:pointer;transition:.2s var(--ease)
}
.ghost svg{width:15px;height:15px}
.ghost .wv{opacity:.25;transition:opacity .2s}
.ghost em{font-style:normal}
.ghost:hover{border-color:var(--line-2);color:var(--ink)}
.ghost[aria-pressed="true"]{color:var(--ink);border-color:color-mix(in srgb,var(--teal) 55%,transparent)}
.ghost[aria-pressed="true"] .wv{opacity:1}

input[type=range]{
  -webkit-appearance:none;appearance:none;width:74px;height:20px;background:none;cursor:pointer;
  opacity:.5;transition:opacity .2s
}
.sound input[type=range]{opacity:.85}
.sound:hover input[type=range]{opacity:1}
input[type=range]::-webkit-slider-runnable-track{height:2px;border-radius:2px;background:var(--line-2)}
input[type=range]::-moz-range-track{height:2px;border-radius:2px;background:var(--line-2)}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:11px;height:11px;border-radius:50%;background:var(--teal);margin-top:-4.5px;
  box-shadow:0 0 0 3px color-mix(in srgb,var(--teal) 22%,transparent)
}
input[type=range]::-moz-range-thumb{width:11px;height:11px;border:none;border-radius:50%;background:var(--teal)}

/* The one thing you have to press. It used to be the same size as every control
   beside it, which made the entry point easy to miss — so it is now bigger than
   its neighbours, and it breathes until it has been used once. */
.play{
  display:inline-flex;align-items:center;gap:.7rem;
  font-family:var(--mono);font-size:.8rem;letter-spacing:.17em;text-transform:uppercase;
  color:#04100f;
  background:linear-gradient(100deg,var(--teal),var(--lav));
  border:none;border-radius:999px;padding:1rem 2.1rem;cursor:pointer;
  transition:padding .22s var(--ease), font-size .22s var(--ease),
             transform .22s var(--ease), filter .22s var(--ease), box-shadow .22s var(--ease);
  box-shadow:0 12px 34px -12px color-mix(in srgb,var(--teal) 90%,transparent);
}
.play:hover{transform:translateY(-1px);filter:brightness(1.07);
  box-shadow:0 16px 40px -12px color-mix(in srgb,var(--teal) 95%,transparent)}
.play:active{transform:translateY(0)}
.play .tri{width:0;height:0;border-left:11px solid currentColor;border-top:7px solid transparent;border-bottom:7px solid transparent}
.play em{font-style:normal}

/* until the first session it carries a slow halo — the only moving thing at rest */
.play.unused{animation:playCall 2.6s var(--ease) infinite}
@keyframes playCall{
  0%,100%{box-shadow:0 12px 34px -12px color-mix(in srgb,var(--teal) 90%,transparent),
                     0 0 0 0 color-mix(in srgb,var(--teal) 50%,transparent)}
  55%    {box-shadow:0 12px 34px -12px color-mix(in srgb,var(--teal) 90%,transparent),
                     0 0 0 15px color-mix(in srgb,var(--teal) 0%,transparent)}
}
.play.unused:hover{animation:none}

/* once running it steps back down — it is no longer the thing to look at */
.play.running{background:none;color:var(--ink);box-shadow:inset 0 0 0 1px var(--line-2);
  font-size:.63rem;letter-spacing:.15em;padding:.66rem 1.3rem;gap:.55rem;animation:none}
.play.running:hover{filter:none;box-shadow:inset 0 0 0 1px var(--teal)}
.play.running .tri{width:9px;height:10px;border:none;background:currentColor;border-radius:1.5px}

.status{
  margin-top:.85rem;display:flex;justify-content:space-between;gap:.6rem 1rem;flex-wrap:wrap;
  font-family:var(--mono);font-size:.56rem;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)
}
#left{color:var(--teal);opacity:.9}

.foot{
  padding:1.5rem clamp(1rem,4vw,2rem) 1.8rem;display:flex;justify-content:space-between;gap:1.2rem;flex-wrap:wrap;
  font-family:var(--mono);font-size:.53rem;letter-spacing:.08em;color:var(--dim);opacity:.7;
  transition:opacity .5s var(--ease)
}

/* ---------- keys --------------------------------------------------------- */

.keys{
  position:fixed;right:clamp(1rem,4vw,2rem);top:4.6rem;z-index:6;width:min(300px,86vw);
  padding:1.1rem 1.2rem;border-radius:18px;border:1px solid var(--line);
  background:color-mix(in srgb,var(--bg) 86%,transparent);
  -webkit-backdrop-filter:blur(26px);backdrop-filter:blur(26px);
  box-shadow:var(--lift);
  animation:pop .26s var(--ease)
}
@keyframes pop{from{opacity:0;transform:translateY(-6px)}}
.keys h2{font-family:var(--mono);font-size:.56rem;letter-spacing:.24em;text-transform:uppercase;
  color:var(--dim);font-weight:600;margin-bottom:.75rem}
.keys dl{display:grid;grid-template-columns:auto 1fr;gap:.5rem .9rem;align-items:center}
.keys dd{font-size:.76rem;color:var(--dim)}
kbd{
  font-family:var(--mono);font-size:.6rem;padding:.2rem .42rem;border-radius:6px;
  border:1px solid var(--line);background:var(--glass-2);color:var(--ink)
}
.keys p{margin-top:.9rem;padding-top:.8rem;border-top:1px solid var(--line);
  font-size:.7rem;line-height:1.55;color:var(--dim);opacity:.85}

/* ---------- the two shapes of the page ----------------------------------- */

/* running: the editor folds to a strip, the tuning row gets out of the way */
body.running .editor{height:72px}
body.running .hint{display:none}
body.running .row-tune,
body.running .note{
  /* min-height would beat max-height, so it has to come down too */
  max-height:0;min-height:0;opacity:0;margin-top:0;padding-top:0;border-top-color:transparent;
  overflow:hidden;pointer-events:none
}
.row-tune,.note{max-height:22rem;opacity:1;transition:max-height .5s var(--ease),opacity .35s var(--ease),
  padding-top .5s var(--ease),margin-top .5s var(--ease)}

/* untouched for a while: everything but the breath goes away */
body.focus .top,
body.focus .dock,
body.focus .foot{opacity:0;pointer-events:none}
body.focus .dock{transform:translateY(14px)}
body.focus .stage{min-height:60vh}

@media(max-width:820px){
  .readout{margin-left:0;gap:1.3rem;width:100%;justify-content:space-between}
  .ro{text-align:left}
  .editor{height:180px}
  .transport{margin-left:0;width:100%;justify-content:space-between}
  .privacy{display:none}
  .foot{flex-direction:column;gap:.4rem}
  .dock{border-radius:20px}
}
@media(max-width:520px){
  /* four across, or `rest` drops to a lonely second row */
  .steppers{display:grid;grid-template-columns:repeat(4,1fr);width:100%;gap:.3rem}
  .step{padding:.26rem .1rem}
  .step .val{min-width:0}
  .step button{width:20px}
  .sessions{order:3}
  .play{flex:1;justify-content:center}
  .hint{width:100%;order:3}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important}
  .orb{filter:blur(80px)}
}
