/* Portie — portieapp.app.
 *
 * tokens.css holds the m7kni design system; this file is the only place that
 * composes it. No raw hex, no invented scale: if the system has a token, use
 * it. Two literals are sanctioned by the design spec — #1f232c for the phone
 * bezel, notch and the dot in the Portie icon, and #fff for text on the accent
 * fill.
 *
 * The root here is 16px, which is what the tokens are authored against, so
 * --m7-root-basis stays at its default of 1. Do NOT add a basis declaration:
 * that correction exists for Material's 20px root, and applying it here would
 * shrink the whole type scale to 80%.
 *
 * tokens.css (base.css) already provides the border-box reset, body colour and
 * family, link colour and hover, :focus-visible, the press scale and the
 * transition set. Everything below is what it does not.
 */

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

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/JetBrainsMono-Variable.woff2") format("woff2-variations");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

/* ── Page ─────────────────────────────────────────────────────────────── */

html { scroll-behavior: smooth; }

/* base.css sets the family, colour and background but not this. */
body { margin: 0; }

/* The sticky header is 60px tall, so an anchor target landing flush to the top
   sits behind it. The prototype does not do this; the handoff asks for it. */
#top, #how, #privacy, #waitlist { scroll-margin-top: 60px; }

img { max-width: 100%; }

.p-shell { max-width: 1120px; margin: 0 auto; padding: 0 1.5rem; }

.p-eyebrow {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-accent);
}

.p-h2 {
  margin: 0.75rem 0 0;
  font-size: 2.25rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 700;
  color: var(--color-ink);
}

/* Motion: one curve, one rise, no bounce and no parallax. tokens.css collapses
   animation and transition duration under prefers-reduced-motion; smooth
   scrolling is neither, so it is switched off explicitly below. */
@keyframes p-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

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

/* ── Buttons ──────────────────────────────────────────────────────────── */

.p-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 500;
  border: 1px solid transparent;
  border-radius: var(--radius-xl);
  padding: 0.75rem 1.5rem;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  text-decoration: none;
}

.p-btn--accent { background: var(--color-accent); color: #fff; }
/* Hover is a background tint change, never an opacity change. */
.p-btn--accent:hover { background: var(--color-accent-hover); color: #fff; }

.p-btn--ghost {
  background: var(--color-surface);
  border-color: var(--color-border);
  color: var(--color-ink);
}
.p-btn--ghost:hover {
  background: var(--color-canvas);
  border-color: var(--color-border-hover);
  color: var(--color-ink);
}

/* The header CTA: smaller pad, smaller radius. */
.p-btn--sm { padding: 0.4rem 0.875rem; border-radius: var(--radius-lg); box-shadow: none; }

.p-btn--block { width: 100%; padding: 0.8rem 1.5rem; }

.p-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* base.css scales every :active button; a disabled one must not respond. */
.p-btn:disabled:active { transform: none; }

/* ── Header ───────────────────────────────────────────────────────────── */

.p-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in oklab, var(--color-surface) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-border);
}

.p-header__inner { display: flex; align-items: center; gap: 2rem; height: 60px; }

.p-brand { display: flex; align-items: center; gap: 0.625rem; text-decoration: none; }
.p-brand__mark { height: 26px; width: 26px; border-radius: 7px; display: block; }
.p-brand__name {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.p-nav { display: flex; align-items: center; gap: 1.5rem; margin-left: auto; }
.p-nav__link { font-size: 0.875rem; font-weight: 500; color: var(--color-ink-light); }
.p-nav__link:hover { color: var(--color-accent); }

/* ── Hero ─────────────────────────────────────────────────────────────── */

.p-hero {
  position: relative;
  overflow: hidden;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.p-hero__wash {
  position: absolute;
  top: -320px;
  right: -220px;
  width: 780px;
  height: 780px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--color-accent-subtle) 0%, transparent 70%);
}

.p-hero__grid {
  position: relative;
  padding-top: 80px;
  padding-bottom: 72px;
  display: grid;
  /* min(Npx, 100%), not a bare Npx. auto-fit collapses the COLUMN COUNT to one
     below the threshold, but the min track keeps its fixed width — so under a
     viewport narrower than that, the single column is still Npx wide and pushes
     a horizontal scrollbar onto the whole page. Measured at 320px before the
     fix: document scrollWidth 425 against a 305px viewport. The min() wrapper
     changes nothing at or above Npx, which is every width the design specifies. */
  grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
  gap: 4rem;
  align-items: center;
}

.p-hero__copy { animation: p-rise var(--duration-slow) var(--ease-standard) both; }

.p-swatches { display: flex; gap: 4px; margin-bottom: 1.5rem; }
.p-swatches__bar { width: 28px; height: 4px; border-radius: 2px; display: block; }
.p-swatches__bar--accent  { background: var(--color-accent); }
.p-swatches__bar--product { background: var(--color-accent-product); }
.p-swatches__bar--chart   { background: var(--color-chart-2); }
.p-swatches__bar--warn    { background: var(--color-warn); }

/* State is always a tinted pill; the accent is a solid fill or a link. Never a
   solid-filled badge. */
.p-status {
  margin: 0 0 1rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-accent);
  background: var(--color-accent-light);
  border-radius: var(--radius-full);
  padding: 0.3rem 0.7rem;
}

.p-hero__title {
  margin: 0;
  font-size: 60px;
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--color-ink);
  max-width: 16ch;
}

.p-hero__lede {
  margin: 1.5rem 0 0;
  max-width: 52ch;
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--color-ink-light);
}

.p-hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }

.p-hero__device { display: flex; justify-content: center; }

/* ── Phone mock (placeholder geometry, not a screenshot) ──────────────── */

.p-phone {
  width: 300px;
  height: 614px;
  border-radius: 44px;
  background: #1f232c;
  padding: 11px;
  box-shadow: var(--shadow-lg);
  flex: none;
}

.p-phone__screen {
  position: relative;
  height: 100%;
  border-radius: 33px;
  background: var(--color-surface);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.p-phone__notch {
  position: absolute;
  top: 9px;
  left: 50%;
  transform: translateX(-50%);
  width: 86px;
  height: 22px;
  border-radius: var(--radius-full);
  background: #1f232c;
  z-index: 2;
}

.p-phone__header { padding: 44px 18px 14px; border-bottom: 1px solid var(--color-border); }

.p-phone__eyebrow {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.p-phone__title {
  margin: 5px 0 0;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.p-phone__body {
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}

.p-phone__stats { display: flex; gap: 8px; }

.p-phone__stat {
  flex: 1;
  background: var(--color-canvas-deep);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 10px;
}

/* The grey placeholder blocks. One accent-coloured element per group implies
   selection; everything else is inert. */
.p-bar { border-radius: 4px; background: var(--color-border); }
.p-bar--accent { background: var(--color-accent); opacity: 0.85; }
.p-bar--deep { background: var(--color-canvas-deep); border-radius: 3px; }

.p-phone__chart {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 74px;
  background: var(--color-canvas-deep);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 10px;
}

.p-phone__chartbar { flex: 1; border-radius: 2px; background: var(--color-border); }
.p-phone__chartbar--accent { background: var(--color-accent); opacity: 0.85; }

.p-phone__list { display: flex; flex-direction: column; gap: 9px; }

.p-phone__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
}
.p-phone__row--dim { opacity: 0.55; }

.p-phone__square {
  height: 26px;
  width: 26px;
  border-radius: 6px;
  background: var(--color-canvas-deep);
  flex: none;
}
.p-phone__square--accent { background: var(--color-accent-light); }

.p-phone__rowtext { flex: 1; }

.p-phone__tabs {
  border-top: 1px solid var(--color-border);
  padding: 11px 18px 20px;
  display: flex;
  justify-content: space-between;
}

.p-phone__tab {
  height: 22px;
  width: 22px;
  border-radius: 6px;
  background: var(--color-canvas-deep);
}
.p-phone__tab--accent { background: var(--color-accent); opacity: 0.85; }

/* ── Supported exports ────────────────────────────────────────────────── */

.p-exports {
  background: var(--color-canvas);
  border-bottom: 1px solid var(--color-border);
  padding: 40px 0;
}

.p-exports__inner { display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem 2.5rem; }

.p-exports__label {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-muted);
}

.p-exports__pills { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.p-pill {
  font-family: var(--font-mono);
  font-size: 0.875rem;
  color: var(--color-ink-light);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: 0.35rem 0.85rem;
}

/* ── Statement ────────────────────────────────────────────────────────── */

.p-statement {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  padding: 80px 0;
}

.p-statement__measure { max-width: 62ch; }

.p-statement__lead,
.p-statement__follow {
  font-size: 1.375rem;
  line-height: 1.55;
  letter-spacing: -0.01em;
}

.p-statement__lead { margin: 0; color: var(--color-ink); }
.p-statement__follow { margin: 1.5rem 0 0; color: var(--color-ink-light); }

.p-code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--color-canvas-deep);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  padding: 1px 5px;
  /* master_metadata_album_artist_name is one unbreakable 34-character token,
     ~400px at this size, and the sentence's whole point is that it is absurdly
     long. Without this it is what puts a horizontal scrollbar on the page at
     320px. `anywhere` breaks only when it must, so nothing changes at any
     width where it already fits. */
  overflow-wrap: anywhere;
}

/* ── How it works ─────────────────────────────────────────────────────── */

.p-how { background: var(--color-canvas); padding: 88px 0; }

.p-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 1.5rem;
  margin-top: 2.5rem;
}

.p-card {
  position: relative;
  overflow: hidden;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  padding: 2rem;
  box-shadow: var(--shadow-panel);
}

.p-card__rule { position: absolute; top: 0; left: 0; right: 0; height: 3px; display: block; }
.p-card__rule--accent  { background: var(--color-accent); }
.p-card__rule--product { background: var(--color-accent-product); }
.p-card__rule--chart   { background: var(--color-chart-2); }

.p-card__head { display: flex; align-items: center; gap: 0.75rem; }

.p-tile {
  height: 44px;
  width: 44px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-xl);
}
.p-tile--accent  { background: var(--color-accent-light); color: var(--color-accent); }
.p-tile--product { background: var(--color-accent-product-light); color: var(--color-accent-product); }
/* The chart series has no tint token of its own, so it is mixed at the same
   14% the design specifies. */
.p-tile--chart {
  background: color-mix(in oklab, var(--color-chart-2) 14%, transparent);
  color: var(--color-chart-2);
}

.p-card__step {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-muted);
}

.p-card__title {
  margin: 2px 0 0;
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 600;
  color: var(--color-ink);
}

.p-card__body {
  margin: 1.25rem 0 0;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--color-ink-light);
}

/* ── Privacy (the product's) ──────────────────────────────────────────── */

.p-privacy {
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  padding: 80px 0;
}

.p-privacy__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 3rem;
  align-items: start;
}

.p-privacy__lede {
  margin: 1rem 0 0;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--color-ink-faint);
}

.p-privacy__rows { display: grid; gap: 1rem; }

.p-prow {
  display: flex;
  gap: 1rem;
  background: var(--color-canvas);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: 1.25rem 1.5rem;
}

/* A bare icon, not a tile. */
.p-prow__icon { color: var(--color-accent); margin-top: 2px; display: flex; flex: none; }

.p-prow__title { margin: 0; font-size: 1rem; font-weight: 600; color: var(--color-ink); }

.p-prow__body {
  margin: 0.375rem 0 0;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--color-ink-faint);
}

/* ── Waitlist ─────────────────────────────────────────────────────────── */

.p-waitlist { background: var(--color-canvas); padding: 88px 0; }

.p-panel {
  background: var(--color-accent-subtle);
  border: 1px solid color-mix(in oklab, var(--color-accent) 22%, transparent);
  border-radius: var(--radius-2xl);
  padding: 2.5rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 2.5rem;
  align-items: center;
}

.p-panel__title {
  margin: 0;
  font-size: 1.75rem;
  letter-spacing: -0.02em;
  line-height: 1.2;
  font-weight: 700;
  color: var(--color-ink);
}

.p-panel__body {
  margin: 0.75rem 0 0;
  max-width: 44ch;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--color-ink-light);
}

.p-form { display: flex; flex-direction: column; gap: 0.875rem; }

.p-field { display: flex; flex-direction: column; gap: 0.375rem; }

.p-field__label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-ink-light);
}

.p-field__input {
  width: 100%;
  /* 1rem, not the 0.875rem the rest of the controls use. Safari on iOS zooms
     the viewport on focusing any field below 16px, and this page is aimed at
     iPhone users. The design does not specify an input size, so this costs no
     fidelity. */
  font-family: var(--font-sans);
  font-size: 1rem;
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: 0.75rem 0.875rem;
}

.p-field__input::placeholder { color: var(--color-muted); }

/* An accent border plus a 1px accent ring, as the design specifies for inputs
   — on top of the outline base.css already gives every focus-visible target. */
.p-field__input:focus-visible {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
}

.p-field__select {
  appearance: none;
  /* Room for the chevron. */
  padding-right: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23717784' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.875rem center;
}

/* Interaction-only, so it occupies no height unless Turnstile actually
   surfaces a challenge. Nothing is reserved for it deliberately — a permanent
   gap in a five-element form is more visible than the widget itself. */
.p-turnstile:empty { display: none; }

.p-form__consent {
  margin: 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--color-ink-faint);
}

/* The `hidden` attribute loses to any class that sets `display`, and .p-note
   sets flex — without this the success and error panels paint as empty
   coloured bars under the button on every page load. !important because the
   attribute is the authority on whether an element is in the page at all. */
[hidden] { display: none !important; }

.p-note {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  border-radius: var(--radius-lg);
  padding: 0.6rem 0.75rem;
}
.p-note--ok { color: var(--color-success); background: var(--color-success-light); }
.p-note--error { color: var(--color-ember); background: var(--color-ember-light); }

/* Success collapses the form to the confirmation. Re-offering the fields
   invites a duplicate signup and burns a fresh challenge each time. */
.p-form--done .p-field,
.p-form--done .p-turnstile,
.p-form--done .p-form__consent,
.p-form--done .p-btn { display: none; }

/* ── Footer ───────────────────────────────────────────────────────────── */

.p-footer { background: var(--color-surface); border-top: 1px solid var(--color-border); }

.p-footer__inner {
  padding-top: 2rem;
  padding-bottom: 2rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.p-footer__brand { display: flex; align-items: center; gap: 0.625rem; }
.p-footer__mark { height: 22px; width: 22px; border-radius: 6px; display: block; }
.p-footer__name { font-size: 0.9375rem; font-weight: 600; color: var(--color-ink); }
.p-footer__domain { font-family: var(--font-mono); font-size: 0.75rem; color: var(--color-muted); }

.p-footer__links { display: flex; gap: 1.5rem; }
.p-footer__links a { font-size: 0.875rem; color: var(--color-muted); }
.p-footer__links a:hover { color: var(--color-accent); }

.p-footer__by { display: flex; align-items: center; gap: 0.5rem; }
.p-footer__byline { font-size: 0.75rem; color: var(--color-muted); }
/* Never filtered, never inverted: inverting turns the mark's jade dot pink. */
.p-footer__wordmark { height: 15px; width: auto; display: block; }

/* ── Prose (privacy notice, transactional pages) ──────────────────────── */

.p-prose { max-width: 68ch; padding: 64px 0 80px; }
.p-prose h1 {
  margin: 0.75rem 0 0;
  font-size: 2.25rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 700;
  color: var(--color-ink);
}
.p-prose h2 {
  margin: 2.5rem 0 0;
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-weight: 600;
  color: var(--color-ink);
}
.p-prose p,
.p-prose li { font-size: 1rem; line-height: 1.65; color: var(--color-ink-light); }
.p-prose p { margin: 1rem 0 0; }
.p-prose ul { margin: 1rem 0 0; padding-left: 1.25rem; }
.p-prose li { margin-top: 0.5rem; }
.p-prose__meta { font-size: 0.875rem; color: var(--color-muted); }

/* The transactional pages: one short centred panel, nothing else. */
.p-outcome { padding: 96px 0 112px; max-width: 52ch; }
.p-outcome h1 {
  margin: 1rem 0 0;
  font-size: 1.75rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 700;
  color: var(--color-ink);
}
.p-outcome p { margin: 1rem 0 0; font-size: 1rem; line-height: 1.65; color: var(--color-ink-light); }
.p-outcome .p-btn { margin-top: 1.5rem; }

/* ── Narrow viewports ─────────────────────────────────────────────────── */

/* Every grid is auto-fit/minmax, so the layout collapses on its own. The one
   exception is the phone mock: it is a fixed 300px with flex:none, and
   300 + 2 x 1.5rem gutters = 348px, which overflows a 320px viewport and gives
   the whole page a horizontal scrollbar. Scale rather than hide — the mock is
   what shows the product, and 320px is the narrowest common phone. */
/* The design specifies no mobile header, and the full one does not fit: brand
   + two text links + the CTA needs ~436px against 272px of content at a 320px
   viewport. The CTA is the page's conversion goal so it stays; the two text
   links go, and both destinations are still reachable from the footer and by
   scrolling. */
@media (max-width: 560px) {
  .p-nav__link { display: none; }
  .p-header__inner { gap: 1rem; }
}

@media (max-width: 400px) {
  .p-hero__device { height: 504px; } /* 614 * 0.82, so the scale leaves no gap */
  .p-phone { transform: scale(0.82); transform-origin: top center; }
  .p-hero__title { font-size: 44px; }
  .p-panel { padding: 1.75rem; }
  /* 4rem between the copy and the mock is a two-column gutter; stacked, it is
     just a hole. */
  .p-hero__grid { gap: 2.5rem; }
}
