/* aineara.com site-wide styles (spec §4). Every value comes from
   /assets/css/tokens.css, which src/tokens.css.njk builds from
   src/_data/tokens.js. Page-only styles live in ascend.css, sillage.css
   and legal.css. */

/* ─── Font ───
   Inter, self-hosted, latin subset only (D15). Apple devices match
   -apple-system first and never download it, so it is never preloaded. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/inter-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ─── Reset ───
   The root font size is left to the browser, so zoom and the reader's own
   text-size setting keep working. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--space-8) + var(--space-4));
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--color-page);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, p, ul, ol, dl, dd, figure, blockquote {
  margin: 0;
}

ul[role="list"],
ol[role="list"] {
  list-style: none;
  padding: 0;
}

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

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
}

[hidden] {
  display: none !important;
}

#main {
  flex: 1 0 auto;
}

/* Links and the focus ring use the text colour (spec §4.1). */
a {
  color: var(--color-text);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: var(--focus-width) solid var(--color-text);
  outline-offset: var(--focus-offset);
}

/* ─── Type ─── */
.display {
  font-size: var(--text-display);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-display);
  text-wrap: balance;
}

.heading {
  font-size: var(--text-heading);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-heading);
  line-height: 1.15;
  text-wrap: balance;
}

.label {
  color: var(--color-text-secondary);
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  letter-spacing: var(--tracking-label);
  line-height: 1.4;
  text-transform: uppercase;
}

/* ─── Layout ─── */
.container {
  width: 100%;
  max-width: calc(var(--container-page) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--reading {
  max-width: calc(var(--container-reading) + 2 * var(--gutter));
}

.section {
  padding-block: var(--space-8);
}

.section--alt {
  background: var(--color-section);
}

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-button);
  background: var(--color-button-bg);
  color: var(--color-button-text);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-4)));
}

.skip-link:focus {
  transform: none;
}

/* ─── Controls ─── */
.icon {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 48px;
  padding: var(--space-3) var(--space-5);
  border: 0;
  border-radius: var(--radius-button);
  font-size: var(--text-small);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  transition: opacity var(--duration-state) var(--ease-state), background-color var(--duration-state) var(--ease-state), color var(--duration-state) var(--ease-state);
}

.button:not(:disabled):hover {
  opacity: 0.88;
}

.button:disabled {
  cursor: default;
}

.button--primary {
  background: var(--color-button-bg);
  color: var(--color-button-text);
}

.button--secondary {
  background: var(--color-fill);
  color: var(--color-text);
}

.field {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-field-border);
  border-radius: var(--radius-field);
  background: var(--color-fill);
  color: var(--color-text);
  font-size: var(--text-body);
  line-height: 1.3;
  transition: border-color var(--duration-state) var(--ease-state);
}

.field::placeholder {
  color: var(--color-text-secondary);
  opacity: 1;
}

.field.is-invalid {
  border-color: var(--color-error);
}

/* ─── Header ─── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--color-page);
  border-bottom: 1px solid var(--color-hairline);
}

.nav {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  min-height: var(--space-8);
  padding-block: var(--space-2);
}

.wordmark {
  color: var(--color-text);
  font-size: var(--text-small);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-decoration: none;
  text-transform: uppercase;
}

.nav .wordmark {
  margin-right: auto;
}

.nav-menu {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
}

.nav-links {
  display: flex;
  gap: var(--space-5);
}

.nav-links a {
  font-size: var(--text-small);
  text-decoration: none;
}

.nav-links a:hover {
  text-decoration: underline;
}

.nav-toggle,
.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text);
  transition: background-color var(--duration-state) var(--ease-state);
}

.nav-toggle:hover,
.theme-toggle:hover {
  background: var(--color-fill);
}

.nav-toggle {
  display: none;
}

html:not(.js) .nav-toggle {
  display: none;
}

/* Lucide keeps its own lucide-<name> class on each icon (see the icon
   shortcode in eleventy.config.js). */
.nav-toggle[aria-expanded="true"] .lucide-menu,
.nav-toggle[aria-expanded="false"] .lucide-x {
  display: none;
}

/* The toggle shows the theme it switches to. */
:root[data-theme="light"] .theme-toggle .lucide-sun,
:root:not([data-theme="light"]) .theme-toggle .lucide-moon {
  display: none;
}

.nav-cta {
  min-height: 40px;
  padding-block: var(--space-2);
}

/* The menu collapses on phones only when JavaScript can open it again. */
@media (max-width: 767.98px) {
  /* Without JS the open, wrapped nav is too tall to stay pinned over in-page targets. */
  html:not(.js) .site-header {
    position: static;
  }

  .js .nav-toggle {
    display: inline-grid;
  }

  .js .nav-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-4);
    padding: var(--space-2) var(--gutter) var(--space-6);
    background: var(--color-page);
    border-bottom: 1px solid var(--color-hairline);
  }

  .js .nav-menu.is-open {
    display: flex;
  }

  .js .nav-links {
    flex-direction: column;
    gap: 0;
  }

  .js .nav-links a {
    display: block;
    padding-block: var(--space-3);
    font-size: var(--text-body);
  }

  .js .nav-menu .theme-toggle {
    align-self: flex-start;
  }
}

/* ─── Footer ─── */
.site-footer {
  padding-block: var(--space-7);
  border-top: 1px solid var(--color-hairline);
  color: var(--color-text-secondary);
  font-size: var(--text-small);
}

.site-footer .container {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.footer-links ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-links a,
.footer-email {
  text-decoration: none;
}

.footer-links a:hover,
.footer-email:hover {
  text-decoration: underline;
}

@media (min-width: 768px) {
  .site-footer .container {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4) var(--space-6);
  }

  .footer-copy {
    margin-right: auto;
  }
}

/* ─── Hero (studio) ─── */
.hero {
  padding-block: var(--space-9) var(--space-8);
}

.hero .label {
  margin-bottom: var(--space-4);
}

.hero .display {
  max-width: 18ch;
}

.hero .display + p {
  max-width: 40rem;
  margin-top: var(--space-5);
  color: var(--color-text-secondary);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

@media (min-width: 1024px) {
  .section {
    padding-block: var(--space-9);
  }

  .hero {
    padding-block: var(--space-10) var(--space-9);
  }
}

/* ─── Ascend scope ───
   Navy in both themes, as in the app (spec §4.1). */
.scope-ascend {
  background: var(--ascend-surface);
  color: var(--ascend-text);
}

.scope-ascend .label {
  color: var(--ascend-text-secondary);
}

.scope-ascend a:not(.button) {
  color: var(--ascend-text);
}

.scope-ascend .button--primary {
  background: var(--ascend-button-bg);
  color: var(--ascend-button-text);
}

/* Dimming #1A6CF6 into the navy takes white text below 4.5:1, so the
   primary darkens to #1560DC instead (5.62:1). */
.scope-ascend .button--primary:not(:disabled):hover {
  opacity: 1;
  background: var(--ascend-accent-on-light);
}

.scope-ascend .button--secondary {
  background: var(--ascend-button-secondary-bg);
  color: var(--ascend-button-secondary-text);
}

.scope-ascend .field {
  background: var(--ascend-button-secondary-bg);
  border-color: var(--ascend-text-secondary);
  color: var(--ascend-text);
}

.scope-ascend .field::placeholder {
  color: var(--ascend-text-secondary);
}

.scope-ascend .field.is-invalid {
  border-color: var(--ascend-error);
}

.scope-ascend :focus-visible {
  outline-color: var(--ascend-text);
}

/* ─── Sillage scope ───
   Follows the theme. The gold hairline is the scope's border colour, so a
   component only sets border-style and border-width to draw it. */
.scope-sillage {
  background: var(--sillage-page);
  color: var(--sillage-text);
  border-color: var(--sillage-hairline);
}

.scope-sillage .label {
  color: var(--sillage-gold);
}

.scope-sillage a:not(.button) {
  color: var(--sillage-text);
}

.scope-sillage .button--primary {
  background: var(--sillage-button-bg);
  color: var(--sillage-button-text);
}

.scope-sillage .button--secondary {
  background: var(--sillage-surface);
  color: var(--sillage-text);
}

.scope-sillage .field {
  background: var(--sillage-surface);
  border-color: var(--color-field-border);
  color: var(--sillage-text);
}

.scope-sillage .field::placeholder {
  color: var(--sillage-text-secondary);
}

.scope-sillage .field.is-invalid {
  border-color: var(--color-error);
}

.scope-sillage :focus-visible {
  outline-color: var(--sillage-text);
}

/* ─── Reveal ───
   Sections fade up once on entry (spec §4.4). Only JavaScript may hide
   them, so content is always visible without it (spec §6.2). */
.reveal {
  transition: opacity var(--duration-reveal) var(--ease-spring), transform var(--duration-reveal) var(--ease-spring);
}

.js .reveal:not(.is-visible) {
  opacity: 0;
  transform: translateY(16px);
}

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

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }

  .js .reveal,
  .js .reveal:not(.is-visible) {
    opacity: 1;
    transform: none;
  }
}

/* ─── Signup form ───
   One waitlist form for every page (spec §6.3). The invalid border is
   .field.is-invalid, under Controls and each scope. */
.signup {
  width: 100%;
}

.signup-form {
  margin: 0;
}

/* Stacked on phones; one row from the tablet breakpoint. */
.signup-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.signup-row .field {
  flex: 1 1 auto;
  min-width: 0;
}

.signup-row .button {
  flex: 0 0 auto;
  white-space: nowrap;
}

@media (min-width: 768px) {
  .signup-row {
    flex-direction: row;
  }
}

.signup-note,
.signup-status,
.signup-done {
  margin: 0;
  font-size: var(--text-small);
  line-height: var(--leading-body);
}

.signup-note {
  margin-top: var(--space-3);
  color: var(--color-text-secondary);
}

.scope-ascend .signup-note {
  color: var(--ascend-text-secondary);
}

.scope-sillage .signup-note {
  color: var(--sillage-text-secondary);
}

/* The status line only ever holds the invalid or the failure message
   (sending changes the button, success replaces the form), so its text is
   always in the error colour. It stays in the accessibility tree while
   empty so role=status announces the first message. */
.signup-status {
  color: var(--color-error);
}

.scope-ascend .signup-status {
  color: var(--ascend-error);
}

.signup-status:not(:empty) {
  margin-top: var(--space-2);
}

.signup-form.is-sending .button {
  cursor: progress;
}

.signup-done {
  font-size: var(--text-body);
  font-weight: var(--weight-card-title);
}

/* Without JavaScript the form can't send, so it is hidden and the
   <noscript> note shows instead. The note only exists in the DOM when
   scripting is off, so it needs no rule to hide it otherwise. */
html:not(.js) .signup-form {
  display: none;
}

noscript .signup-nojs {
  display: block;
  margin: 0;
  font-size: var(--text-small);
  line-height: var(--leading-body);
}

noscript .signup-nojs a {
  color: inherit;
  text-decoration: underline;
}

/* ==========================================================================
   Homepage (Task 7): app cards, principles, About and the waitlist strip.
   The Ascend card is navy in both themes (.scope-ascend). The Sillage card
   follows the theme through the --sillage-* tokens (.scope-sillage).
   ========================================================================== */

#apps > .container {
  display: grid;
  gap: var(--space-5);
}

#apps h2.label,
#principles h2.label {
  margin: 0;
}

@media (min-width: 1024px) {
  #apps > .container {
    grid-template-columns: 2fr 1fr;
  }

  #apps h2.label {
    grid-column: 1 / -1;
  }
}

.app-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-6);
  border-radius: var(--radius-hero);
}

@media (min-width: 768px) {
  .app-card {
    padding: var(--space-7);
  }
}

.app-card > * {
  margin: 0;
}

.app-mark {
  width: 64px;
  height: 64px;
  margin-bottom: var(--space-2);
}

.app-card-title {
  font-size: var(--text-card-title);
  font-weight: var(--weight-card-title);
  line-height: 1.2;
}

.app-card-label {
  font-size: var(--text-label);
  font-weight: var(--weight-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.app-card-line {
  font-size: var(--text-body);
  line-height: var(--leading-body);
}

.app-card-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-4);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.app-card-link .icon {
  transition: transform var(--duration-state) var(--ease-state);
}

.app-card-link:hover .icon {
  transform: translateX(3px);
}

/* Ascend card. #4A90F8 on the navy is 5.17:1 or better (spec §4.1). */
.app-card--ascend .app-card-title,
.app-card--ascend .heading,
.app-card--ascend .app-card-link {
  color: var(--ascend-text);
}

.app-card--ascend .app-card-label {
  color: var(--ascend-accent);
}

.app-card--ascend .app-card-line {
  color: var(--ascend-text-secondary);
}

/* Sillage card: gold hairline border, name in the Georgia display face. */
.app-card--sillage {
  border: 1px solid var(--sillage-hairline);
}

.app-card--sillage .app-card-title {
  font-family: var(--font-sillage-display);
  font-size: var(--text-heading);
  font-weight: var(--weight-sillage-display);
  letter-spacing: normal;
  line-height: 1.1;
}

.app-card--sillage .app-card-title,
.app-card--sillage .app-card-link {
  color: var(--sillage-text);
}

.app-card--sillage .app-card-label {
  color: var(--sillage-gold);
}

.app-card--sillage .app-card-line {
  color: var(--sillage-text-secondary);
}

/* Principles: a hairline grid. The 1px gaps and the border show the
   .principles background, which is the hairline colour. */
.principles {
  display: grid;
  gap: 1px;
  margin-top: var(--space-5);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-card);
  background: var(--color-hairline);
  background-clip: padding-box;
  overflow: hidden;
}

@media (min-width: 1024px) {
  .principles {
    grid-template-columns: repeat(3, 1fr);
  }
}

.principle {
  padding: var(--space-6);
  background: var(--color-section);
}

.principle-title {
  margin: 0 0 var(--space-3);
  font-size: var(--text-card-title);
  font-weight: var(--weight-card-title);
  line-height: 1.25;
}

.principle-body {
  margin: 0;
  color: var(--color-text-secondary);
}

/* About: one paragraph on the reading measure. */
.about .label {
  margin: 0;
}

.about .heading {
  max-width: var(--container-reading);
  margin: var(--space-3) 0 var(--space-5);
}

.about p:not(.label) {
  max-width: var(--container-reading);
  margin: 0;
}

/* Waitlist strip: heading beside the form (or the badge) from 1024px. */
.waitlist-strip .container {
  display: grid;
  gap: var(--space-5);
  align-items: center;
}

.waitlist-strip .heading {
  margin: 0;
}

.waitlist-strip .signup {
  width: 100%;
  max-width: 34rem;
}

.waitlist-strip .app-store-badge {
  justify-self: start;
}

@media (min-width: 1024px) {
  .waitlist-strip .container {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-7);
  }

  .waitlist-strip .signup,
  .waitlist-strip .app-store-badge {
    justify-self: end;
  }
}
