/* =====================================================================
   Resona Daily — styles

   Visual language follows the "Tidal" pen the operator supplied:
   deep-ocean navy, a single teal accent, Archivo Black for display type,
   Libre Baskerville italic for prose, Space Mono for labels, hairline
   teal borders, and layered wave separators between sections.

   Every class/id used by app.js is preserved — this is a re-skin, not a
   restructure.
   ===================================================================== */

:root{
  /* palette */
  --ocean-deep:#03111e;
  --ocean-mid:#062035;
  --ocean-light:#0a3550;
  --teal:#00b4c6;
  --teal-dim:#007a88;
  --teal-glow:rgba(0,180,198,.14);
  --sand:#e8d5a3;
  --coral:#ff6b47;
  --white:#f0f4f7;
  --muted:rgba(240,244,247,.4);
  --border:rgba(0,180,198,.12);
  --border2:rgba(240,244,247,.06);

  /* type */
  --f-display:"Archivo Black",system-ui,sans-serif;
  --f-serif:"Libre Baskerville",Georgia,serif;
  --f-mono:"Space Mono",ui-monospace,Menlo,monospace;
  --f-body:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Hiragino Sans","Noto Sans JP",sans-serif;

  /* page gutter — full-bleed elements cancel this with negative margins */
  --gutter:24px;

  /* compat aliases so old rules keep resolving */
  --bg:var(--ocean-deep); --bg2:var(--ocean-mid); --card:#062035;
  --line:var(--border); --fg:var(--white); --mut:var(--muted);
  --acc:var(--teal); --acc2:var(--teal-dim);
  --ok:#00b4c6; --warn:var(--sand);
}

*{box-sizing:border-box}
[hidden]{display:none !important}
html,body{margin:0;padding:0}
html{scroll-behavior:smooth}
body{overflow-x:clip}   /* clip, do not create a scroll container */
body{
  background:var(--ocean-deep);
  color:var(--white);
  font-family:var(--f-serif);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  -webkit-text-size-adjust:100%;
}
a{color:var(--teal);text-decoration:none}
a:hover{color:var(--white)}
.wrap{max-width:1180px;margin:0 auto;padding:0 var(--gutter)}
.wrap.narrow{max-width:760px}
.mono{font-family:var(--f-mono);font-size:11.5px;color:var(--muted);letter-spacing:.06em}

/* ---------------- nav ---------------- */
.topbar{
  position:sticky;top:0;z-index:100;
  background:rgba(3,17,30,.82);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid var(--border2);
}
.topbar .wrap{display:flex;align-items:center;justify-content:space-between;height:68px;gap:16px}
.brand{
  font-family:var(--f-display);font-size:24px;letter-spacing:-.02em;
  color:var(--white);display:flex;align-items:center;gap:10px;line-height:1;
}
.brand span{color:var(--teal)}
.brand::before{
  content:"";width:30px;height:12px;flex:0 0 30px;
  background:
    radial-gradient(circle at 4px 6px,var(--teal) 3.4px,transparent 3.6px),
    radial-gradient(circle at 15px 6px,var(--teal) 3.4px,transparent 3.6px),
    radial-gradient(circle at 26px 6px,var(--teal) 3.4px,transparent 3.6px);
  opacity:.95;
}
.pill{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  padding:8px 16px;border:1px solid var(--border);background:rgba(0,180,198,.05);
  color:var(--muted);border-radius:100px;white-space:nowrap;
}
.pill.member{border-color:rgba(0,180,198,.45);color:var(--teal);background:rgba(0,180,198,.08)}
a.pill:hover{border-color:var(--teal);color:var(--teal)}

main{padding:0 0 20px}
.screen{display:none}
.screen.active{display:block;animation:fade .45s cubic-bezier(.22,.61,.36,1)}
@keyframes fade{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* ---------------- loading ----------------
   The player asks the server who you are before it can draw anything, and that
   request is in flight while the scripts load. This is what fills the gap, so a
   slow connection shows a calm, deliberate wait rather than an empty page.

   Deliberately quiet: three rings breathing out of phase from one centre, in the
   product's own colours, no progress bar (the wait is short and unsized, and a
   bar that jumps to 100% reads as a stall). Under prefers-reduced-motion the
   pulse stops and the mark sits still -- the wait is conveyed by the text. */
.loading{display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-height:52vh;gap:26px}
.loading p{margin:0;color:var(--muted);font-family:var(--f-mono);font-size:12px;
  letter-spacing:.16em;text-transform:uppercase;text-align:center;line-height:1.7}
.loading .ripple{position:relative;width:74px;height:74px}
.loading .ripple i{position:absolute;inset:0;border-radius:50%;
  border:1px solid var(--teal);opacity:0;animation:breathe 3.6s cubic-bezier(.22,.61,.36,1) infinite}
.loading .ripple i:nth-child(2){animation-delay:1.2s}
.loading .ripple i:nth-child(3){animation-delay:2.4s}
.loading .ripple b{position:absolute;left:50%;top:50%;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;
  border-radius:50%;background:var(--teal);box-shadow:0 0 12px var(--teal-glow)}
@keyframes breathe{
  0%{transform:scale(.32);opacity:0}
  22%{opacity:.75}
  100%{transform:scale(1);opacity:0}
}

/* A small rotating ring, for a wait inside a page that is already on screen
   (building the session). A spin reads instantly even in under a second, which
   the breathing rings above cannot: their cycle is 3.6s, so most of one would
   pass unseen. Centred, and no minimum height, so nothing below it moves. */
.spinwrap{display:flex;justify-content:center;align-items:center;margin:0 0 16px}
/* The wait indicator sits on the button, not in a block above it.

   It used to be a row of its own between the length chooser and the button, which
   read as a page-level loading state rather than as feedback for the button that
   was pressed. Inside the button it is unambiguous: the label is hidden while the
   spinner shows, and the spinner is centred over the button's own box, so the
   button does not change size when either appears. */
#genBtn{position:relative}
#genBtn.busy #genLabel{visibility:hidden}
#genBtn .spinwrap{
  position:absolute;left:0;right:0;top:0;bottom:0;margin:0;
  display:flex;align-items:center;justify-content:center;pointer-events:none;
}

.spinwrap .spin{display:block;width:26px;height:26px;border-radius:50%;
  border:2px solid rgba(0,180,198,.22);border-top-color:var(--teal);
  animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---------------- landing audition ----------------
   Sits between the feature list and the sign-in card: hear it, then read what it
   does, then sign up. Centred text so the single button reads as the point. */
.listen{text-align:center}
/* The audition's bar display: the same canvas the session player uses, sized so
   the card does not jump when it appears. */
.listen .viz{margin:0 0 18px;padding:6px 0;border-top:1px solid var(--border2);border-bottom:1px solid var(--border2)}
.listen .viz canvas{display:block;width:100%;height:82px}
.listen .btn{margin:2px 0 14px;min-width:160px}
.listen-lead{margin:0 0 16px;font-family:var(--f-serif);font-size:19px;color:var(--white)}
.listen .hint{margin:0}
/* The line that turns a listener into a member: the product's own sentence for
   what happens after the email field. */
.pitch{margin:26px 0 22px;padding:0 4px;text-align:center;font-family:var(--f-serif);
  font-size:19px;line-height:1.65;color:var(--white)}
@media (max-width:760px){.pitch{font-size:17px;margin:22px 0 18px}}

/* ---------------- session length ---------------- */
.lengths{display:flex;gap:8px;flex-wrap:wrap}
.lengths button{
  font-family:var(--f-mono);font-size:12px;letter-spacing:.1em;
  padding:11px 20px;border:1px solid var(--border);background:transparent;
  color:var(--muted);cursor:pointer;transition:none;
}
.lengths button.on{border-color:var(--teal);color:var(--teal);background:rgba(0,180,198,.08)}
.lengths button:disabled{opacity:.4;cursor:not-allowed}
/* The free tier's fixed length: the same visual language as a chosen option so
   it reads as the answer to the same question, not as a missing control. */
.lengths .fixed{border-color:var(--teal);color:var(--teal);background:rgba(0,180,198,.08);
  padding:11px 20px;font-family:var(--f-mono);font-size:12px;letter-spacing:.1em}

/* ---------------- upgrade panel ---------------- */
.upgrade{margin-top:26px;padding-top:22px;border-top:1px solid var(--border2)}
.up-title{margin:0 0 14px;font-family:var(--f-mono);font-size:9.5px;letter-spacing:.24em;
  text-transform:uppercase;color:var(--teal)}
.up-list{list-style:none;padding:0;margin:0 0 20px;display:grid;gap:2px}
.up-list li{background:rgba(10,53,80,.5);border:1px solid var(--border);padding:14px 18px}
.up-list b{display:block;font-size:14px;color:var(--white);font-weight:550}
.up-list span{display:block;margin-top:3px;font-size:12.5px;color:var(--muted);line-height:1.5}
#upgradeBtn{width:100%}

/* ---------------- hero (animated waves) ---------------- */
/* No `display` here on purpose. A bare #s-landing rule outranks .screen, so
   setting display:flex meant the landing section was visible no matter which
   screen was active — the hero and the email field stayed on the page behind the
   player. The layout comes from #s-landing.active below, which is only one more
   class of specificity but is scoped to the active state, so .screen's
   display:none applies when it is not the current screen. */
#s-landing{
  position:relative;
  overflow:clip;   /* clip horizontally, but let the waves bleed to the edges */
  flex-direction:column;align-items:stretch;justify-content:flex-start;
  min-height:0;
  padding:0;                     /* the wave band must reach both edges, so the
                                    section applies no horizontal padding and
                                    each text column carries the gutter itself */
  background:linear-gradient(180deg,#03111e 0%,#051c30 40%,#072540 60%,#0a3550 80%,#0d4060 100%);
}
#s-landing.active{display:flex}
.hero-sky{
  position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse 80% 50% at 50% 0%,rgba(0,180,198,.08) 0%,transparent 70%);
}
/* Wide side padding on the hero copy: the waves are full-bleed, so the text
   needs its own generous margin to feel deliberate rather than cramped.
   Scoped with #s-landing so it outranks .wrap/.wrap.narrow. */
#s-landing .hero-content{
  position:relative;z-index:2;width:100%;
  margin:0 auto;padding:88px 44px 14px;
}
.hero-below{
  position:relative;z-index:2;width:100%;
  margin:0 auto;padding:0 var(--gutter) 56px;
}
/* Full-bleed band: a direct child of the section, so it spans the viewport
   with no padding to cancel on any device. */
.hero-waves{
  position:relative;z-index:1;pointer-events:none;line-height:0;
  width:100%;margin:0;padding:0;
  overflow:visible;              /* notes leave the band upward */
}
.hero-waves-inner{position:relative;display:block;width:100%;overflow:visible}
.hero-waves-back{position:relative;line-height:0;z-index:0}
.hero-waves-front{position:absolute;inset:0;line-height:0;z-index:2}
.hero-waves-back svg,.hero-waves-front svg{display:block;width:100%}
.hero-waves svg{
  height:clamp(150px,20vh,220px);
  /* Fade the tails into the page so the block has no hard bottom edge. */
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 62%,rgba(0,0,0,.5) 84%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 0%,#000 62%,rgba(0,0,0,.5) 84%,transparent 100%);
}
/* the front wave stays opaque: notes must not show through it */
.hero-waves-front svg{
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 90%,rgba(0,0,0,.9) 100%);
  mask-image:linear-gradient(180deg,#000 0%,#000 90%,rgba(0,0,0,.9) 100%);
}
.hwave{will-change:transform}

/* the other screens keep calm, centred spacing */
.screen:not(#s-landing) > .wrap{padding-top:72px;padding-bottom:60px}

/* ---------------- section headers ---------------- */
.eyebrow,.section-label{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.28em;text-transform:uppercase;
  color:var(--teal);margin:0 0 16px;display:flex;align-items:center;gap:12px;
}
.eyebrow::before{
  content:"";width:26px;height:1px;background:var(--teal);opacity:.6;flex:0 0 26px;
}
h1{
  font-family:var(--f-display);
  /* sized for a ~700px column: large and confident without overflowing */
  font-size:clamp(38px,5.6vw,68px);
  line-height:.94;letter-spacing:-.03em;margin:0 0 26px;font-weight:400;
}
h2{
  font-family:var(--f-display);
  font-size:clamp(30px,4.4vw,54px);
  line-height:1;letter-spacing:-.025em;margin:0 0 22px;font-weight:400;
}
.lede{
  font-family:var(--f-serif);font-style:italic;
  color:var(--muted);margin:0 0 40px;font-size:clamp(16px,1.7vw,20px);line-height:1.7;
  max-width:62ch;
}
.hint{font-family:var(--f-mono);color:var(--muted);font-size:11.5px;letter-spacing:.04em;margin:12px 0 0;line-height:1.6}
.center{justify-content:center}

/* ---------------- feature list ---------------- */
/* The three feature cards sit directly under the wave band, and with no space
   above them they read as part of the water rather than as the page's first
   content block. The top margin is what separates them from it. */
.feats{list-style:none;padding:0;margin:34px 0 44px;display:grid;gap:2px;border:1px solid var(--border)}
.feats li{
  background:rgba(6,32,53,.6);border-right:1px solid var(--border);
  padding:30px 26px;display:grid;gap:6px;transition:background .3s;
}
.feats li:hover{background:rgba(10,53,80,.72)}
.feats b{font-family:var(--f-display);font-weight:400;font-size:18px;line-height:1.25;letter-spacing:-.015em;color:var(--white)}
.feats span{color:var(--muted);font-size:13px;font-style:italic;line-height:1.7}
@media(min-width:760px){
  .feats{grid-template-columns:repeat(3,1fr)}
  .feats li:last-child{border-right:none}
}

/* ---------------- cards ---------------- */
.card{
  background:rgba(6,32,53,.62);
  border:1px solid var(--border);
  border-radius:0;padding:30px;margin:0 0 22px;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.card label{
  display:block;font-family:var(--f-mono);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--muted);margin:0 0 9px;
}
input,select{
  width:100%;padding:16px 18px;border-radius:0;border:1px solid var(--border);
  background:rgba(6,32,53,.8);color:var(--white);font-family:var(--f-mono);
  font-size:13px;margin:0 0 16px;
}
input::placeholder{color:rgba(240,244,247,.28)}
input:focus,select:focus{outline:none;border-color:var(--teal);background:rgba(10,53,80,.8)}
/* Text fields on the account and contact pages.

   There was no rule for .field at all, so a textarea fell back to the browser's
   default box -- about twenty characters wide, in its own font -- while the select
   beside it was full width because `select` is styled on its own. The two looked
   like they came from different pages. Width is 100% and the height is set in rows;
   resizing is vertical only, because a horizontally resizable box in a fixed-width
   column breaks the layout. */
.field{
  display:block;width:100%;box-sizing:border-box;
  padding:15px 18px;border-radius:0;border:1px solid var(--border);
  background:rgba(6,32,53,.8);color:var(--white);
  font-family:var(--f-mono);font-size:13px;line-height:1.6;
  margin:0 0 16px;
}
.field:focus{outline:none;border-color:var(--teal);background:rgba(10,53,80,.8)}
textarea.field{min-height:190px;resize:vertical}

select{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--teal) 50%),linear-gradient(135deg,var(--teal) 50%,transparent 50%);background-position:calc(100% - 20px) 22px,calc(100% - 15px) 22px;background-size:5px 5px,5px 5px;background-repeat:no-repeat}

/* ---------------- buttons ---------------- */
.btn{
  appearance:none;border:1px solid var(--border);background:rgba(10,53,80,.5);
  color:var(--white);padding:15px 26px;border-radius:0;
  font-family:var(--f-mono);font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  cursor:pointer;transition:.2s;white-space:nowrap;
}
.btn:hover{border-color:var(--teal);color:var(--teal);background:rgba(0,180,198,.08)}
.btn.primary{
  background:var(--teal);border-color:var(--teal);color:var(--ocean-deep);
  font-weight:700;
}
.btn.primary:hover{background:var(--white);border-color:var(--white);color:var(--ocean-deep)}
.btn:disabled{opacity:.4;cursor:not-allowed}
.row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}

/* ---------------- check-in controls ---------------- */
.qs{margin:0 0 26px}
.qs>label{
  font-family:var(--f-mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--white);margin-bottom:12px;
}
.scale,.intents{display:grid;gap:2px}
.scale{grid-template-columns:repeat(5,1fr)}
.intents{grid-template-columns:repeat(3,1fr)}
.scale button,.intents button{
  padding:14px 6px;border:1px solid var(--border);background:rgba(3,17,30,.6);
  color:var(--muted);font-family:var(--f-mono);font-size:12px;letter-spacing:.08em;
  cursor:pointer;transition:.2s;
}
.scale button:hover,.intents button:hover{border-color:rgba(0,180,198,.4);color:var(--white)}

/* An option the current plan does not include: shown, labelled, and not
   selectable. Dimming alone would read as 'broken'; the label says why. */
/* Scoped to accounts that do NOT have plus. The class is on the element
   permanently (it marks which options belong to the paid plan), so without the
   body scope a plus member would see their own options dimmed and labelled as
   something they lack. */
body:not(.is-plus) .scale button.plus,
body:not(.is-plus) .intents button.plus,
body:not(.is-plus) .lengths button.plus{
  position:relative;opacity:.55;cursor:not-allowed;
}
body:not(.is-plus) .scale button.plus:hover,
body:not(.is-plus) .intents button.plus:hover,
body:not(.is-plus) .lengths button.plus:hover{
  border-color:var(--border);color:var(--muted);
}
body:not(.is-plus) .intents button.plus::after,
body:not(.is-plus) .lengths button.plus::after{
  content:"plus";position:absolute;top:3px;right:5px;
  font-size:8px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--sand);opacity:.95;
}
.scale button.on,.intents button.on{
  border-color:var(--teal);color:var(--ocean-deep);background:var(--teal);font-weight:700;
}

/* What each end of a 1-5 scale means, and what the current answer does to the
   session. Without these the numbers carry no meaning to the visitor. */
.scalekeys{display:flex;justify-content:space-between;margin-top:6px;
  font-size:11px;color:var(--muted);letter-spacing:.02em;gap:10px}
.scalekeys span:last-child{text-align:right}
@media (max-width:520px){
  .scalekeys{font-size:10px}
}

/* ---------------- player ---------------- */
.player{padding:0}
.player .viz{
  border-bottom:1px solid var(--border);background:rgba(3,17,30,.9);
  margin-bottom:0;overflow:hidden;
}
#viz{display:block;width:100%;height:150px}
.player > *:not(.viz){margin-left:30px;margin-right:30px}
.player > .row{margin-top:8px}
.timebar{height:2px;background:rgba(240,244,247,.08);margin-top:26px;overflow:hidden}
#timefill{height:100%;width:0;background:var(--teal);transition:width .25s linear;box-shadow:0 0 12px var(--teal-glow)}
.timerow{
  display:flex;justify-content:space-between;font-family:var(--f-mono);
  color:var(--muted);font-size:11px;letter-spacing:.1em;margin:10px 0 22px;
}
.spec pre{
  white-space:pre-wrap;word-break:break-word;font-family:var(--f-mono);
  font-size:11.5px;color:var(--muted);margin:16px 0 0;line-height:1.7;
  background:rgba(3,17,30,.7);border:1px solid var(--border);padding:18px;
}
.spec summary{
  cursor:pointer;font-family:var(--f-mono);font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);
}
.spec summary:hover{color:var(--teal)}

#summaryBox{font-size:14px;font-style:italic;color:var(--muted)}
#summaryBox .kv{
  display:flex;justify-content:space-between;gap:14px;
  border-bottom:1px solid var(--border2);padding:12px 0;font-style:normal;
}
#summaryBox .kv:last-child{border-bottom:none}
#summaryBox .kv span:first-child{font-family:var(--f-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
#summaryBox .kv i{font-style:normal;color:var(--white)}

/* ---------------- stack / chips ---------------- */
.stack{margin-top:26px;border-top:1px solid var(--border2);padding-top:20px}

/* The player card sets padding:0 so the visualiser can run full width, and every
   child but the visualiser gets side margins instead. Nothing gave the underside a
   margin, so the instrument chips sat one pixel above the card's bottom border --
   measured: card padding 0 on all sides, chips bottom to card bottom 1px. The
   closing space is put on the last block rather than on the card, because padding on
   .player would also push the visualiser in from the sides. */
.player > .stack{margin-bottom:30px}
.player > *:last-child:not(.viz){margin-bottom:30px}
.stacklabel{
  font-family:var(--f-mono);font-size:9.5px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--teal);margin:18px 0 10px;
}
.stacklabel:first-child{margin-top:0}
.chips{display:flex;flex-wrap:wrap;gap:2px}
.chip{
  display:inline-flex;align-items:center;gap:9px;line-height:1.35;
  font-family:var(--f-mono);font-size:11px;letter-spacing:.06em;
  border:1px solid var(--border);background:rgba(10,53,80,.55);
  padding:9px 15px;color:var(--white);border-radius:0;
}
.chip i{font-style:normal;color:var(--teal);font-size:10.5px}

ul.credits{list-style:none;padding:0;margin:0;display:grid;gap:2px}
ul.credits li{
  background:rgba(6,32,53,.6);border:1px solid var(--border);
  padding:18px;font-size:13px;color:var(--muted);font-style:italic;
}
ul.credits b{
  color:var(--white);font-family:var(--f-mono);font-weight:400;display:block;
  margin-bottom:4px;font-size:11px;letter-spacing:.12em;text-transform:uppercase;font-style:normal;
}

/* ---------------- section separators (the pen's layered waves) ------------ */
.wave-sep{
  display:block;width:100%;line-height:0;overflow:hidden;pointer-events:none;
  margin:0;
}
.wave-sep svg{display:block;width:100%;height:clamp(60px,10vw,150px)}

/* ---------------- footer ---------------- */
footer{
  border-top:1px solid var(--border2);margin-top:0;padding:64px 0 72px;
  background:linear-gradient(180deg,var(--ocean-deep) 0%,#020c16 100%);
}
.disc{color:var(--muted);font-size:12.5px;line-height:1.8;margin:0 0 20px;font-style:italic;max-width:70ch}
.disc b{
  color:var(--white);font-family:var(--f-mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;display:block;margin-bottom:8px;font-style:normal;font-weight:400;
}
.flinks{font-family:var(--f-mono);color:var(--muted);font-size:10.5px;letter-spacing:.12em;margin:0;text-transform:uppercase}
.flinks a{color:var(--muted)}
.flinks a:hover{color:var(--teal)}

/* ---------------- responsive ---------------- */
@media (max-width:760px){
  :root{--gutter:18px}
  .wrap{padding:0 var(--gutter)}

  /* --- header: compact, never wider than the screen --- */
  .topbar .wrap{
    height:auto;min-height:54px;gap:8px;
    flex-wrap:wrap;padding-top:10px;padding-bottom:10px;
  }
  .brand{font-size:18px;flex:0 0 auto}
  .brand::before{display:none}
  .pill,.pill-btn{
    padding:6px 10px;font-size:9px;letter-spacing:.08em;
    max-width:44vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  /* the two status pills and the logout control share a line under the logo */
  #libLink,#planPill{margin-left:0}
  .topbar .wrap{row-gap:8px}

  /* --- hero: headline, one-line intro, then the waves --------------- */
  /* More room around the hero copy on a phone: the headline was sitting too
     close to the header and to the screen edges. */
  /* Specificity guard: these must beat .wrap/.wrap.narrow (0,2,0). */
  #s-landing .hero-content{padding:64px 28px 26px}
  #s-landing .hero-below{padding:0 28px 52px}
  .eyebrow{margin-bottom:12px;font-size:9.5px;letter-spacing:.2em}
  h1{font-size:clamp(34px,10.4vw,46px);line-height:1.0;margin-bottom:16px}
  h2{font-size:clamp(26px,7.4vw,36px)}

  /* the lede is the only long paragraph above the fold: trim it */
  #s-landing .lede{
    font-size:14.5px;line-height:1.6;margin-bottom:24px;
    display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;
  }

  .hero-waves svg{height:150px}

  /* --- everything below the waves ---------------------------------- */
  .screen:not(#s-landing) > .wrap{padding-top:36px;padding-bottom:44px}
  .feats{margin:26px 0 28px}
  .feats li{padding:22px 20px}
  .feats b{font-size:16.5px}
  .card{padding:20px}
  .lede{font-size:15px;margin-bottom:26px}

  .player > *:not(.viz){margin-left:20px;margin-right:20px}
  #viz{height:100px}
  .intents{grid-template-columns:repeat(2,1fr)}
  .row{gap:8px}
  .row .btn{flex:1 1 auto;padding:14px 14px;font-size:10.5px}

  footer{padding:48px 0 56px}
  .disc{font-size:12px}
}

@media (max-height:700px){
  .hero-waves svg{height:96px}
  #s-landing .lede{-webkit-line-clamp:3}
}
@media (max-width:420px){
  .scale{grid-template-columns:repeat(5,1fr)}
  .scale button,.intents button{font-size:11px;padding:12px 4px}
}

/* =====================================================================
   Hero atmosphere — mystical light + musical notes

   Purely decorative: every element is aria-hidden and pointer-events:none,
   and the copy keeps z-index above all of it.
   ===================================================================== */
.hero-glow{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}

/* Soft halos: slow, out-of-phase breathing so the light never pulses in unison. */
.halo{
  position:absolute;border-radius:50%;
  filter:blur(60px);opacity:.5;
  background:radial-gradient(circle,rgba(0,180,198,.55) 0%,rgba(0,180,198,.14) 42%,transparent 72%);
  animation:halo-breathe 19s ease-in-out infinite;
  will-change:transform,opacity;
}
.halo-1{width:58vw;height:58vw;max-width:640px;max-height:640px;left:-8%;top:-6%;animation-duration:21s}
.halo-2{
  width:46vw;height:46vw;max-width:520px;max-height:520px;right:-6%;top:6%;
  background:radial-gradient(circle,rgba(120,90,230,.42) 0%,rgba(120,90,230,.10) 44%,transparent 72%);
  animation-duration:27s;animation-delay:-7s;
}
.halo-3{
  width:52vw;height:52vw;max-width:560px;max-height:560px;left:26%;bottom:-14%;
  background:radial-gradient(circle,rgba(232,213,163,.30) 0%,rgba(232,213,163,.08) 46%,transparent 74%);
  animation-duration:23s;animation-delay:-13s;
}
@keyframes halo-breathe{
  0%,100%{opacity:.34;transform:translate3d(0,0,0) scale(1)}
  50%{opacity:.68;transform:translate3d(0,-14px,0) scale(1.09)}
}

/* The note field is the water surface the glyphs rise out of. */
/* The field spans the band but does NOT clip: glyphs must be able to rise up
   over the headline area. The band has overflow:visible for the same reason. */
.note-field{position:absolute;left:0;right:0;top:0;bottom:0;pointer-events:none;overflow:visible;z-index:1}

.note{
  position:absolute;display:block;color:var(--teal);
  opacity:0;will-change:transform,opacity;
  animation-name:note-rise;animation-timing-function:linear;animation-iteration-count:infinite;
  transform-origin:50% 82%;      /* pivot near the note head, like real water lift */
}
.note svg{display:block;width:100%;height:100%;
  filter:drop-shadow(0 0 10px rgba(0,180,198,.6));
}

/* Depth: far glyphs are smaller, dimmer and softer; near ones are crisp. */
.note--far{color:rgba(150,215,240,.92);filter:blur(var(--blur,.6px));z-index:0}
.note--mid{color:rgba(190,225,255,.95);filter:blur(var(--blur,.35px));z-index:1}
.note--near{color:var(--teal);z-index:2}
.note:nth-child(5n).note--near{color:rgba(232,213,163,.95)}   /* a few warm ones */

/* Emergence: start at the crest, clipped by the field, brighten as it clears
   the water, then fade and drift as it climbs. --spin carries a random
   direction and amount, so glyphs tumble either way. */
@keyframes note-rise{
  0%   {opacity:0;                 transform:translate3d(0,0,0) rotate(var(--spin0,0deg)) scale(.5)}
  9%   {opacity:calc(var(--peak,.5) * .5);
        transform:translate3d(0,-2%,0) rotate(var(--spin0,0deg)) scale(.72)}
  22%  {opacity:var(--peak,.5);
        transform:translate3d(calc(var(--drift,0px) * .2),calc(var(--rise,-38vh) * .2),0)
                 rotate(var(--spin1,6deg)) scale(1)}
  64%  {opacity:calc(var(--peak,.5) * .8);
        transform:translate3d(calc(var(--drift,0px) * .64),calc(var(--rise,-38vh) * .64),0)
                 rotate(var(--spin1,6deg)) scale(1.03)}
  100% {opacity:0;
        transform:translate3d(var(--drift,0px),var(--rise,-38vh),0)
                 rotate(var(--spin2,18deg)) scale(1.07)}
}

/* Faint motes: tiny points of light that twinkle where they drift. */
.mote{
  position:absolute;border-radius:50%;background:rgba(190,235,255,.9);
  animation-name:mote-twinkle;animation-timing-function:ease-in-out;animation-iteration-count:infinite;
  will-change:opacity,transform;
}
@keyframes mote-twinkle{
  0%,100%{opacity:0;transform:scale(.7)}
  50%{opacity:var(--peak,.3);transform:scale(1.15)}
}

/* Under reduced-motion the hero keeps its glow but nothing moves. */
@media (prefers-reduced-motion: reduce){
  .halo,.note,.mote{animation:none !important}
  .note--far,.note--mid,.note--near{filter:none}
  .halo{opacity:.42}
  .note,.mote{display:none}
  /* The loading rings stop, but the mark stays visible so the wait is still
     legible without movement. */
  .loading .ripple i{animation:none !important;opacity:.22;transform:scale(.9)}
  /* Slowed rather than stopped: a motionless ring reads as a broken one. */
  .spinwrap .spin{animation-duration:1.8s}
}

/* On phones: fewer, smaller, and slower — battery first. */
@media (max-width:760px){
  .halo{filter:blur(44px);opacity:.4}
  .halo-1{width:78vw;height:78vw}
  .halo-2{width:64vw;height:64vw}
  .halo-3{width:70vw;height:70vw}
  .note-field{opacity:.8}
}

/* A pill that is a button: same shape as the status pills, but tappable. */
.pill-btn{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  padding:8px 16px;border:1px solid var(--border);background:transparent;
  color:var(--muted);border-radius:100px;cursor:pointer;white-space:nowrap;
  transition:border-color .2s,color .2s;
}
.pill-btn:hover{border-color:var(--teal);color:var(--teal)}
.pill-btn:disabled{opacity:.5;cursor:default}

