/* Roasting Core — landing page
   Palette lifted from the app: near-black panels, the orange of the exhaust
   curve as the highlight, and the blue / pink of the other live curves. */

:root {
  color-scheme: dark;

  --bg:            #080807;
  --bg-raised:     #0f0e0d;
  --bg-panel:      #141211;
  --border:        #232221;
  --border-strong: #332f2c;

  --text:          #eeebe8;
  --text-muted:    #a6a09a;
  --text-faint:    #77716b;

  --orange:        #f97316;
  --orange-dim:    #3d2210;
  --blue:          #5b9cf6;
  --pink:          #ef6ba8;

  --radius:        14px;
  --radius-sm:     9px;
  --wrap:          1120px;

  --shadow-lg:     0 30px 70px -25px rgba(0,0,0,.85);
}

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 24px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--orange);
  color: #1d0b02;
  padding: 10px 16px;
  border-radius: 0 0 var(--radius-sm) 0;
  font-weight: 600;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(8, 8, 7, .78);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-block: 14px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
}

.brand-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--orange);
  box-shadow: 0 0 0 4px rgba(249, 115, 22, .16);
  flex: none;
  /* Same 2.4s beat as the hero status pill, so the two breathe together. */
  animation: beacon 2.4s ease-in-out infinite;
}

@keyframes beacon {
  0%, 100% {
    box-shadow: 0 0 0 3px rgba(249, 115, 22, .18);
    opacity: 1;
  }
  50% {
    box-shadow: 0 0 0 7px rgba(249, 115, 22, .04);
    opacity: .72;
  }
}

@media (prefers-reduced-motion: reduce) {
  .brand-dot { animation: none; }
}

.brand-name {
  font-weight: 650;
  letter-spacing: -0.01em;
  font-size: 1.05rem;
}
.brand-name.small { font-size: .95rem; }

.site-nav {
  display: flex;
  align-items: center;
  gap: 8px;
}

.site-nav > a:not(.btn) {
  color: var(--text-muted);
  text-decoration: none;
  font-size: .93rem;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
}
.site-nav > a:not(.btn):hover { color: var(--text); }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 22px;
  border-radius: 999px;
  border: 1px solid transparent;
  font: inherit;
  font-weight: 600;
  font-size: .95rem;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .16s ease, border-color .16s ease,
              color .16s ease, transform .16s ease;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--orange);
  color: #1d0b02;
}
.btn-primary:hover { background: #ff8a33; }

.btn-ghost {
  border-color: var(--border-strong);
  color: var(--text);
  background: transparent;
}
.btn-ghost:hover { border-color: #4a443e; background: rgba(255,255,255,.03); }

.btn-small { padding: 9px 16px; font-size: .88rem; }
.btn-block { width: 100%; }

/* .btn sets a display, which would otherwise beat the browser's own rule for
   the hidden attribute and show a button that is meant to be put away. */
.btn[hidden] { display: none; }

:where(a, button, input):focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}

/* ---------- hero ---------- */

.hero { padding-top: 84px; }

.hero-inner { text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 26px;
  padding: 6px 15px 6px 12px;
  border: 1px solid var(--orange-dim);
  background: rgba(249, 115, 22, .07);
  border-radius: 999px;
  color: var(--orange);
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.pulse {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--orange);
  flex: none;
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .35; }
}
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }

h1 {
  margin: 0 auto 22px;
  max-width: 16ch;
  font-size: clamp(2.4rem, 6.5vw, 4.2rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
  font-weight: 680;
}

.lede {
  margin: 0 auto;
  max-width: 60ch;
  font-size: clamp(1.02rem, 1.9vw, 1.2rem);
  color: var(--text-muted);
}

.lede-follow {
  margin: 1em auto;
  max-width: 60ch;
  font-size: clamp(1.02rem, 1.9vw, 1.2rem);
  color: var(--text-muted);
}


.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 34px;
}

.hero-note {
  margin: 18px 0 0;
  font-size: .85rem;
  color: var(--text-faint);
}

/* ---------- screenshot ---------- */

.shot-wrap {
  position: relative;
  margin-top: 62px;
  padding-bottom: 96px;
}

.shot-glow {
  position: absolute;
  inset: -6% 8% 32%;
  background:
    radial-gradient(60% 60% at 30% 40%, rgba(91, 156, 246, .20), transparent 70%),
    radial-gradient(55% 55% at 70% 45%, rgba(239, 107, 168, .16), transparent 70%),
    radial-gradient(60% 50% at 50% 15%, rgba(249, 115, 22, .16), transparent 70%);
  filter: blur(60px);
  pointer-events: none;
  z-index: 0;
}

.shot {
  position: relative;
  z-index: 1;
  margin: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-panel);
  box-shadow: var(--shadow-lg);
}

/* ---------- features ---------- */

.features {
  position: relative;
  overflow: hidden;
  border-top: 1px solid var(--border);
  background: linear-gradient(180deg, var(--bg-raised), var(--bg));
  padding-block: 88px;
}

/* The three curve colours, blurred and parked behind the grid, so the cards
   sit in light rather than on flat black. */
.features::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(40% 55% at 6% 18%,   rgba(249, 115, 22, .16), transparent 70%),
    radial-gradient(38% 50% at 94% 40%,  rgba(91, 156, 246, .14), transparent 70%),
    radial-gradient(45% 45% at 50% 105%, rgba(239, 107, 168, .12), transparent 70%);
  filter: blur(60px);
  pointer-events: none;
}
.features > .wrap { position: relative; }

.section-title {
  margin: 0 0 48px;
  text-align: center;
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  letter-spacing: -0.025em;
  font-weight: 650;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Each card is tinted by its icon's colour: a gradient border that runs from
   the accent at the top-left corner down into the ordinary border, and a
   wash of the same colour in that corner. --edge is the accent's strength
   on the border, registered so it can tween on hover. */
@property --edge {
  syntax: '<number>';
  inherits: false;
  initial-value: .45;
}

.feature {
  --accent: 166, 160, 154;
  --edge: .45;
  position: relative;
  overflow: hidden;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 26px 24px 28px;
  background:
    linear-gradient(var(--bg-panel), var(--bg-panel)) padding-box,
    linear-gradient(150deg,
      rgba(var(--accent), var(--edge)) 0%,
      var(--border) 45%,
      var(--border-strong) 100%) border-box;
  transition: --edge .22s ease, transform .18s ease, box-shadow .22s ease;
}
.feature::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(75% 65% at 0% 0%, rgba(var(--accent), .16), transparent 70%);
  opacity: .8;
  transition: opacity .22s ease;
  pointer-events: none;
}
.feature > * { position: relative; }

.feature:hover {
  --edge: 1;
  transform: translateY(-2px);
  box-shadow: 0 24px 50px -28px rgba(var(--accent), .55);
}
.feature:hover::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .feature:hover { transform: none; } }

.feature[data-accent="orange"] { --accent: 249, 115, 22; }
.feature[data-accent="blue"]   { --accent: 91, 156, 246; }
.feature[data-accent="pink"]   { --accent: 239, 107, 168; }

.feature-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  margin-bottom: 18px;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
}
.feature-icon svg { width: 21px; height: 21px; }

.feature[data-accent="orange"] .feature-icon { color: var(--orange); }
.feature[data-accent="blue"]   .feature-icon { color: var(--blue); }
.feature[data-accent="pink"]   .feature-icon { color: var(--pink); }
.feature[data-accent] .feature-icon {
  border-color: rgba(var(--accent), .30);
  background: rgba(var(--accent), .08);
  box-shadow: 0 0 18px -6px rgba(var(--accent), .6);
}

.feature h3 {
  margin: 0 0 9px;
  font-size: 1.06rem;
  font-weight: 630;
  letter-spacing: -0.012em;
}

.feature p {
  margin: 0;
  color: var(--text-muted);
  font-size: .95rem;
}

.features-footnote {
  margin: 40px auto 0;
  max-width: 62ch;
  text-align: center;
  color: var(--text-faint);
  font-size: .93rem;
}

/* ---------- signup ---------- */

.signup {
  border-top: 1px solid var(--border);
  padding-block: 88px;
  /* The panel's glow overhangs it on both sides; on a phone that was 19px of
     sideways scroll. Clip (not hidden) so the section is not a scroll
     container and the glow still spills up and down. */
  overflow-x: clip;
}

/* The blurb is the panel's first row, under the section title, rather than a
   paragraph floating between the two — that was mostly air. */
.signup-intro {
  margin: 0 0 4px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  font-size: .95rem;
}

/* Two columns of fields: the panel is wide enough that one column of short
   inputs left a lot of air, and the message box needs the width anyway. */
.signup-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px 24px;
  align-items: start;
  max-width: 760px;
  margin-inline: auto;
  background: var(--bg-panel);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 30px;
  box-shadow: var(--shadow-lg);
}

/* The message box, its toggle, the button and the status line run both
   columns. */
.field-wide { grid-column: 1 / -1; }

/* The message box is folded away behind this until it's wanted — most people
   have nothing to add, and an empty four-row box made the form look like
   more work than it is. */
.disclosure {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: -6px 0;
  padding: 6px 2px;
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font: inherit;
  font-size: .88rem;
  font-weight: 600;
  cursor: pointer;
  transition: color .16s ease;
}
.disclosure:hover { color: var(--text); }

/* A plus turned through 45° is a close cross, so the one glyph says both
   states. */
.disclosure-icon {
  width: 15px;
  height: 15px;
  color: var(--orange);
  transition: transform .18s ease;
}
.disclosure[aria-expanded="true"] .disclosure-icon { transform: rotate(45deg); }

.field label {
  display: block;
  margin-bottom: 8px;
  font-size: .88rem;
  font-weight: 600;
  letter-spacing: .01em;
}

.optional {
  margin-left: 6px;
  font-weight: 500;
  color: var(--text-faint);
  font-size: .82rem;
  letter-spacing: 0;
}

.field input,
.field textarea {
  width: 100%;
  padding: 12px 14px;
  background-color: #0c0b0a;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  font: inherit;
  font-size: .95rem;
  transition: border-color .16s ease, background-color .16s ease;
}
.field input::placeholder,
.field textarea::placeholder { color: #6a635d; }
.field input:hover,
.field textarea:hover  { border-color: #45403b; }
.field input:focus,
.field textarea:focus  { border-color: var(--orange); background-color: #100e0c; }

.field input[aria-invalid="true"] { border-color: var(--pink); }

/* Sent. The box goes entirely — border, fill and side padding — and what is
   left is the answer as text under its label. Dimming a field that still
   looks like a field reads as "disabled, try again later"; taking the field
   away reads as "this is what you sent", which is what happened. */
.field input[readonly],
.field textarea[readonly] {
  padding-inline: 0;
  background-color: transparent;
  border-color: transparent;
  color: var(--text-muted);
  cursor: default;
}
.field input[readonly]:hover,
.field textarea[readonly]:hover,
.field input[readonly]:focus,
.field textarea[readonly]:focus {
  border-color: transparent;
  background-color: transparent;
}

/* The text is still selectable, so it is still reachable by keyboard, so it
   still has to show where the focus is — just as an outline rather than as
   the border of a box that is no longer there. */
.field input[readonly]:focus-visible,
.field textarea[readonly]:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}

/* Sized to its content by the script, so the message doesn't sit in four
   rows of empty box it no longer needs. */
.field textarea[readonly] {
  min-height: 0;
  resize: none;
}

.disclosure:disabled {
  color: var(--text-faint);
  cursor: default;
}
.disclosure:disabled:hover { color: var(--text-faint); }
.disclosure:disabled .disclosure-icon { color: var(--text-faint); }

.field textarea {
  min-height: 96px;
  resize: vertical;
  line-height: 1.5;
}

.hint  { margin: 8px 0 0; font-size: .82rem; color: var(--text-faint); }
.error { margin: 8px 0 0; font-size: .82rem; color: var(--pink); }

.form-note {
  margin: 0;
  text-align: center;
  font-size: .82rem;
  color: var(--text-faint);
}
/* Focused after a submit, never tabbed to — a ring here would mark a line of
   text as something to interact with, which it isn't. */
.form-note:focus { outline: none; }

.form-note.is-success { color: var(--orange); }
/* The same colour the inline field errors use, so one thing means one thing. */
.form-note.is-error   { color: var(--pink); }

/* ---------- 404 ---------- */

/* Far too little on the page to fill a screen, so the footer is pinned to the
   bottom and the message sits in the middle of what's left. Hung off a body
   class rather than applied to every page: the landing page is long enough
   that it would only get in the way there. */
.page-notfound {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page-notfound main {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
}

.notfound {
  width: 100%;
  padding-block: clamp(48px, 10vh, 104px);
}

.notfound-curve {
  display: block;
  width: min(260px, 72%);
  height: auto;
  margin: 0 auto 32px;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nf-axis  { stroke: var(--border-strong); stroke-width: 2; }
.nf-curve { stroke: var(--orange); stroke-width: 3.5; }
/* Where the roast would have gone. Dotted, and in the axis colour, so it
   reads as absence rather than as a second curve. */
.nf-ghost { stroke: var(--border-strong); stroke-width: 3; stroke-dasharray: 2 11; }
.nf-stop  { fill: var(--bg); stroke: var(--orange); stroke-width: 3.5; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--border);
  padding-block: 28px;
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.footer-meta {
  color: var(--text-faint);
  font-size: .85rem;
}

/* ---------- narrow ---------- */

@media (max-width: 820px) {
  .signup-form { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .wrap { padding-inline: 18px; }
  .hero { padding-top: 56px; }
  .shot-wrap { margin-top: 44px; padding-bottom: 68px; }
  .features, .signup { padding-block: 64px; }
  .site-nav > a:not(.btn) { display: none; }
  .signup-form { padding: 24px 20px; }
  .hero-actions .btn { width: 100%; }
}

/* A stage the same width as the form, so the glow has somewhere to sit. */
.form-stage {
  position: relative;
  max-width: 760px;
  margin-inline: auto;
}
.form-stage > .signup-form { position: relative; z-index: 1; }

/* ---------- signup panel ----------
   Rotating conic gradient border (painted on the border-box, panel colour
   on the padding-box), warm glow beneath, gradient button. */

@property --ember-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.v-ember {
  --ember-angle: 0deg;
  border: 1px solid transparent;
  background:
    linear-gradient(var(--bg-panel), var(--bg-panel)) padding-box,
    conic-gradient(from var(--ember-angle),
      var(--orange) 0deg,
      var(--pink)   110deg,
      var(--blue)   220deg,
      var(--orange) 360deg) border-box;
  box-shadow:
    var(--shadow-lg),
    0 0 80px -20px rgba(249, 115, 22, .45),
    0 0 120px -40px rgba(239, 107, 168, .35);
  animation: ember-spin 9s linear infinite;
}
@keyframes ember-spin { to { --ember-angle: 360deg; } }
@media (prefers-reduced-motion: reduce) { .v-ember { animation: none; } }

.v-ember-stage::before {
  content: "";
  position: absolute;
  inset: 20% -8% -12%;
  background:
    radial-gradient(50% 60% at 30% 100%, rgba(249, 115, 22, .28), transparent 70%),
    radial-gradient(50% 60% at 75% 100%, rgba(239, 107, 168, .22), transparent 70%);
  filter: blur(50px);
  pointer-events: none;
  z-index: 0;
}

.v-ember .field input,
.v-ember .field textarea {
  background-color: rgba(8, 8, 7, .7);
  border-color: rgba(255, 255, 255, .09);
  transition: border-color .16s ease, box-shadow .2s ease, background-color .16s ease;
}
.v-ember .field input:hover,
.v-ember .field textarea:hover { border-color: rgba(249, 115, 22, .35); }
.v-ember .field input:focus,
.v-ember .field textarea:focus {
  border-color: var(--orange);
  box-shadow: 0 0 0 4px rgba(249, 115, 22, .18), 0 0 24px -4px rgba(249, 115, 22, .5);
  outline: none;
}

/* A sent field, inside the panel. The panel repaints the fill, the border and
   the focus glow, so the sent state has to be restated here or it is painted
   straight back over — but only those, the rest of it is up with the other
   [readonly] rules. */
.v-ember .field input[readonly],
.v-ember .field textarea[readonly],
.v-ember .field input[readonly]:hover,
.v-ember .field textarea[readonly]:hover,
.v-ember .field input[readonly]:focus,
.v-ember .field textarea[readonly]:focus {
  background-color: transparent;
  border-color: transparent;
  box-shadow: none;
}
.v-ember .field input[readonly]:focus-visible,
.v-ember .field textarea[readonly]:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}

.v-ember .btn-primary {
  background: linear-gradient(120deg, #ff8a33 0%, var(--orange) 45%, var(--pink) 100%);
  color: #1d0b02;
  box-shadow: 0 10px 34px -10px rgba(249, 115, 22, .75), 0 0 0 1px rgba(255, 255, 255, .08) inset;
  transition: box-shadow .2s ease, transform .16s ease, filter .16s ease;
}
.v-ember .btn-primary:hover {
  filter: brightness(1.08);
  box-shadow: 0 14px 44px -10px rgba(249, 115, 22, .9), 0 0 0 1px rgba(255, 255, 255, .12) inset;
}
