/* =========================================================================
   CypherScan — privacy-first document analysis
   Mobile-first. Every scale-up is an explicit min-width query.
   ========================================================================= */

/* ---------- Tokens ---------- */
:root {
  /* Palette: near-black ground, warm off-white text, bright silver as the single
     accent. The silver is deliberately cooler than the text so it still reads as
     an accent rather than just "more white". */
  --ink:        #0B0B0C;
  --ink-raised: #141416;
  --ink-sunk:   #08080A;
  --slate:      #6E7076;
  --slate-lit:  #9A9CA2;
  --cream:      #EFE8DA;
  --cream-dim:  #C9C2B6;
  --silver:     #C6CEDA;
  --silver-lit: #E8EDF5;

  /* Gold, reserved for the three signature moments: the headline, the primary
     action, and the boundary. A flat hex cannot read as metal — the impression
     comes from light raking across the surface, so the gold is a gradient with
     a pale highlight, a deep shadow, and a second highlight at the far edge. */
  --gold:       #D4B570;
  --gold-lit:   #F2E3B6;
  --gold-deep:  #9E7A38;
  --gold-text:  #E3C88C; /* flat, for type too small to show a gradient */
  --silver-deep: #8E99A8;
  --silver-sheen: linear-gradient(
    148deg,
    #FFFFFF 0%,
    #E2E8F2 28%,
    var(--silver-deep) 55%,
    #E2E8F2 74%,
    #FFFFFF 100%
  );
  --gold-sheen: linear-gradient(
    148deg,
    var(--gold-lit) 0%,
    var(--gold) 30%,
    var(--gold-deep) 55%,
    var(--gold) 74%,
    var(--gold-lit) 100%
  );
  --warn:       #E5A85F;
  --danger:     #C4553D;
  --hair:       rgba(239, 232, 218, 0.10);

  --font-display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --font-body: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", "Cascadia Mono", monospace;

  /* Vertical rhythm — mobile values. Deliberately tight so a phone screen
     shows a section boundary rather than one endless column. */
  --section-y: 4rem;
  --gutter: 1.25rem;
  --stack: 1.5rem;
  --measure: 34ch;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 240ms;
}

@media (min-width: 48em) {
  :root {
    --section-y: 6.5rem;
    --gutter: 2rem;
    --stack: 2rem;
    --measure: 46ch;
  }
}

@media (min-width: 64em) {
  :root {
    --section-y: 9rem;
    --gutter: 3rem;
    --measure: 52ch;
  }
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }

/* The hidden attribute has to win, always. Ordinary component rules such as
   `.preview__stage canvas { display: block }` outrank the user agent's
   `[hidden] { display: none }` on specificity, which silently leaves elements
   on screen after the code has "hidden" them — two previews stacked on top of
   each other, and nothing in the JavaScript to blame. */
[hidden] { display: none !important; }

a { color: inherit; }

/* =========================================================================
   Falling glyphs
   Latin, Cyrillic, kana and han, drifting down behind the entire page. The
   tool reads documents in every script, so the ornament states something true
   rather than decorating. It is fixed to the viewport, sits under everything,
   and each section lays a pool of ink over it (see .section::before) so the
   glyphs survive only in the negative space around the type and the tool.
   ========================================================================= */
.rain {
  position: fixed;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0.46;
}
@media (min-width: 48em) {
  .rain { opacity: 0.64; }
}

/* Everything the visitor reads or touches rides above the rain. */
main, .header, .footer { position: relative; z-index: 1; }

.hero,
.section,
.footer {
  isolation: isolate;
  position: relative;
}

/* The ink pool. Densest where the copy sits, thinning out toward the far edge,
   so the rain is never behind a sentence but is still visible on the page. */
.section::before {
  content: "";
  position: absolute;
  inset: -3rem 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    86% 64% at 26% 50%,
    var(--ink) 28%,
    rgba(11, 11, 12, 0.82) 55%,
    rgba(11, 11, 12, 0.34) 78%,
    transparent 100%
  );
}

/* The footer closes the page, so it is solid ink edge to edge — the rain stops
   there rather than trailing off behind the small print. */
.footer::before {
  content: "";
  position: absolute;
  inset: -4rem 0 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 0%, var(--ink) 34%, var(--ink) 100%);
}

/* The hero is where the effect earns its place, so its pool is lighter — enough
   to keep the headline crisp, not enough to clear the whole opening. */
.hero::before {
  content: "";
  position: absolute;
  inset: -2rem 0 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    82% 62% at 27% 44%,
    rgba(11, 11, 12, 0.95) 26%,
    rgba(11, 11, 12, 0.62) 58%,
    transparent 100%
  );
}

:focus-visible {
  outline: 2px solid var(--silver-lit);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--silver); color: var(--ink); }

.shell {
  width: 100%;
  max-width: 76rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.skip-link {
  position: absolute;
  top: 0; left: 50%;
  transform: translate(-50%, -110%);
  z-index: 100;
  background: var(--silver);
  color: var(--ink);
  padding: 0.65rem 1.1rem;
  font-size: 0.875rem;
  font-weight: 500;
  border-radius: 0 0 4px 4px;
  transition: transform var(--dur) var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* ---------- Type scale ----------
   Mobile sizes are chosen for a 375px screen first, not derived by shrinking
   the desktop figure. Display faces get tighter tracking as they grow. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--silver);
  margin: 0 0 1.0625rem;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-variation-settings: "SOFT" 0, "WONK" 1, "opsz" 40;
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.125rem, 1.55rem + 2.45vw, 4.75rem);
  /* Fraunces carries deep descenders. At 1.06 the g in "Belgeniz" ran into the
     line below and sat too close to the sub-heading to read cleanly. */
  line-height: 1.16;
  letter-spacing: -0.022em;
}

h2 {
  font-size: clamp(1.75rem, 1.35rem + 1.7vw, 3.25rem);
  line-height: 1.12;
  letter-spacing: -0.018em;
}

h3 {
  font-size: 1.0625rem;
  line-height: 1.35;
  letter-spacing: -0.008em;
}
@media (min-width: 48em) {
  h3 { font-size: 1.25rem; }
}

.lede {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--cream-dim);
  max-width: var(--measure);
  margin: 0;
}
@media (min-width: 48em) {
  .lede { font-size: 1.125rem; }
}

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

.section__head { margin-bottom: 2.25rem; }
@media (min-width: 48em) {
  .section__head { margin-bottom: 3.5rem; }
}

/* ---------- Header ---------- */
.header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--ink) 86%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--hair);
}

.header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 3.5rem;
}
@media (min-width: 48em) {
  .header__bar { min-height: 4.5rem; }
}

/* Brand: tracking is compressed on small screens so the wordmark reads as one
   object next to the hamburger instead of sprawling across the bar. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-variation-settings: "WONK" 1, "opsz" 20;
  letter-spacing: -0.015em;
  text-decoration: none;
  white-space: nowrap;
}
@media (min-width: 48em) {
  .brand {
    font-size: 1.25rem;
    gap: 0.625rem;
    letter-spacing: 0.005em;
  }
}

.brand__mark {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--silver);
  flex: none;
  overflow: visible; /* the beam runs past the viewBox on both sides */
}
/* The beam is the one gold stroke in the mark, exactly as it is on the page. */
.brand__mark .brand__beam { stroke: var(--gold); }
.brand:hover .brand__mark .brand__beam { stroke: var(--gold-lit); }
.brand__mark .brand__beam,
.brand:hover .brand__mark .brand__beam { transition: stroke var(--dur) var(--ease); }

/* ---------- Navigation ---------- */
.nav--desktop { display: none; }

@media (min-width: 48em) {
  .nav--desktop {
    display: flex;
    align-items: center;
    gap: 2rem;
  }
  .nav--desktop a {
    font-size: 0.9375rem;
    color: var(--cream-dim);
    text-decoration: none;
    transition: color var(--dur) var(--ease);
  }
  .nav--desktop a:hover { color: var(--cream); }
}

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-right: -0.5rem;
  background: none;
  border: 0;
  color: var(--cream);
  cursor: pointer;
}
@media (min-width: 48em) { .menu-toggle { display: none; } }

.menu-toggle__box { width: 20px; height: 12px; position: relative; }
.menu-toggle__box span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transition: transform var(--dur) var(--ease), opacity 120ms linear;
}
.menu-toggle__box span:nth-child(1) { top: 0; }
.menu-toggle__box span:nth-child(2) { top: 50%; transform: translateY(-50%); }
.menu-toggle__box span:nth-child(3) { bottom: 0; }

.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.25px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.25px) rotate(-45deg); }

/* Mobile drawer: full-width sheet under the bar. Links are full-row targets
   so the whole strip is tappable, not just the glyph. */
.nav--mobile {
  display: block;
  overflow: hidden;
  max-height: 0;
  border-top: 0 solid var(--hair);
  transition: max-height 320ms var(--ease);
}
.nav--mobile[data-open="true"] {
  max-height: 24rem;
  border-top-width: 1px;
}
@media (min-width: 48em) { .nav--mobile { display: none; } }

.nav--mobile ul {
  list-style: none;
  margin: 0;
  padding: 0.5rem 0 1.25rem;
}
.nav--mobile a {
  display: block;
  padding: 0.875rem 0;
  font-size: 1.0625rem;
  color: var(--cream-dim);
  text-decoration: none;
  border-bottom: 1px solid var(--hair);
}
.nav--mobile li:last-child a { border-bottom: 0; }

/* ---------- Language switch ---------- */
.lang {
  display: flex;
  align-items: center;
  gap: 0.125rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
}
.lang a {
  padding: 0.4rem 0.45rem;
  color: var(--slate);
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  transition: color var(--dur) var(--ease);
}
.lang a:hover { color: var(--cream-dim); }
.lang a[aria-current="true"] { color: var(--silver); }

.nav--mobile .lang { padding-top: 1rem; gap: 0.5rem; }
.nav--mobile .lang a { padding: 0.5rem 0.25rem; font-size: 0.8125rem; }

/* ---------- Hero ---------- */
.hero { padding-block: 3.25rem 0; }
@media (min-width: 48em) { .hero { padding-block: 5rem 0; } }

.hero > .shell { position: relative; z-index: 1; }

.hero__title { margin-bottom: 1.4375rem; color: var(--gold); }

/* The sheen is applied per word rather than to the headline as a whole. Each
   word is transformed by the reveal animation, and a transformed descendant
   does not reliably inherit a parent's text-clipped background — the letters
   end up transparent over nothing, which is to say invisible. Flat gold stays
   as the fallback wherever background-clip: text is unavailable. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero__title .reveal-word {
    background: var(--gold-sheen);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
.hero__sub { margin-bottom: 2rem; }

/* Word-by-word reveal */
.reveal-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.4em);
  animation: word-in 620ms var(--ease) forwards;
  animation-delay: calc(var(--i) * 55ms);
}
@keyframes word-in {
  to { opacity: 1; transform: none; }
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 3rem;
}
@media (min-width: 48em) { .hero__actions { margin-bottom: 4.5rem; } }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.875rem;
  padding: 0.75rem 1.4rem;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1;
  border: 1px solid transparent;
  border-radius: 2px;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur) var(--ease),
              color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform 120ms var(--ease);
}
.btn:active { transform: translateY(1px); }

/* Primary actions carry the same metal as the headline. */
.btn--primary {
  background: var(--gold-sheen);
  background-size: 100% 100%;
  color: var(--ink);
}
.btn--primary:hover { background-size: 140% 140%; }
.btn--primary:disabled {
  background: var(--slate);
  color: var(--ink-sunk);
  cursor: not-allowed;
}

/* The secondary action is the same metal treatment in silver: a brushed border
   and lettering, on the dark ground rather than filled — so it reads as clearly
   subordinate to the gold primary while belonging to the same set. */
/* The secondary action is the same polished-metal treatment as the primary,
   struck in silver instead of gold. */
.btn--ghost {
  background: var(--silver-sheen);
  background-size: 100% 100%;
  color: var(--ink);
  border-color: transparent;
  transition: background-size 420ms var(--ease), transform 120ms var(--ease);
}
.btn--ghost:hover { background-size: 140% 140%; }

.btn--quiet {
  min-height: 2.25rem;
  padding: 0.4rem 0.75rem;
  font-size: 0.8125rem;
  background: none;
  border-color: var(--hair);
  color: var(--slate-lit);
}
.btn--quiet:hover { color: var(--cream); border-color: var(--slate); }

@media (max-width: 29.99em) {
  .hero__actions .btn { flex: 1 1 100%; }
}

/* ---------- Signature: the boundary ----------
   A silver hairline labelled on both sides. Everything above it happens on the
   visitor's machine; everything below it is the network. It is the one piece
   of ornament on the page, and it is describing the actual architecture. */
.boundary {
  position: relative;
  padding-block: 1.75rem;
}

.boundary__rule {
  position: relative;
  height: 1px;
  background: linear-gradient(90deg,
    transparent,
    var(--gold-deep) 8%,
    var(--gold-lit) 30%,
    var(--gold) 55%,
    var(--gold-lit) 80%,
    transparent);
}

.boundary__rule::after {
  content: "";
  position: absolute;
  inset: -1px 0;
  background: linear-gradient(90deg, transparent, var(--gold-lit), transparent);
  opacity: 0;
  filter: blur(3px);
}
.boundary[data-crossing="true"] .boundary__rule::after {
  animation: rule-pulse 1.4s var(--ease) infinite;
}
@keyframes rule-pulse {
  0%, 100% { opacity: 0; }
  50% { opacity: 0.7; }
}

.boundary__label {
  position: absolute;
  right: 0;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate);
  white-space: nowrap;
}
.boundary__label--above { top: 0.35rem; }
.boundary__label--below { bottom: 0.35rem; }

.boundary__note {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  padding-right: 0.75rem;
  background: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* Flat gold, not the sheen: at 10px a gradient would only muddy the letters. */
  color: var(--gold-text);
}
/* On narrow screens the note would collide with the labels — drop it below. */
@media (max-width: 33.99em) {
  .boundary__note {
    position: static;
    transform: none;
    display: block;
    padding: 0.75rem 0 0;
    background: none;
  }
  .boundary__label--below { bottom: auto; top: calc(100% + 2.25rem); }
  .boundary { padding-bottom: 3.5rem; }
}

/* Text crossing the line during analysis */
.crossing {
  position: absolute;
  left: 0; right: 0;
  top: 50%;
  height: 0;
  pointer-events: none;
  overflow: visible;
}
.crossing span {
  position: absolute;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  color: var(--gold-lit);
  opacity: 0;
  animation: cross 1.8s linear infinite;
}
@keyframes cross {
  0%   { opacity: 0; transform: translateY(-2.5rem); }
  20%  { opacity: 0.9; }
  80%  { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(2.5rem); }
}

/* ---------- Steps ---------- */
.steps {
  display: grid;
  gap: 0;
  counter-reset: step;
}
@media (min-width: 56em) {
  .steps {
    grid-template-columns: repeat(3, 1fr);
    gap: 2.5rem;
  }
}

.step {
  position: relative;
  counter-increment: step;
  padding-block: 1.5rem;
}
@media (min-width: 56em) {
  .step { padding-block: 1.75rem 0; }
}

.step__n {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  color: var(--silver);
  display: block;
  margin-bottom: 0.75rem;
}
.step__n::before { content: counter(step, decimal-leading-zero); }

.step h3 { margin-bottom: 0.5rem; }
.step p {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--slate-lit);
  line-height: 1.6;
}

/* ---------- Analyser ---------- */
.analyser {
  border: 1px solid var(--hair);
  border-radius: 3px;
  background: var(--ink-raised);
}

.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  padding: 2.5rem 1.25rem;
  text-align: center;
  border: 1px dashed rgba(239, 232, 218, 0.16);
  border-radius: 3px;
  margin: 0.75rem;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
@media (min-width: 48em) {
  .dropzone { padding: 4rem 2rem; margin: 1rem; }
}
.dropzone:hover,
.dropzone[data-drag="true"] {
  border-color: var(--silver);
  background: rgba(198, 206, 218, 0.05);
}

.dropzone__icon { width: 1.75rem; height: 1.75rem; color: var(--silver); }
.dropzone__label { font-size: 1rem; font-weight: 500; }
.dropzone__hint { font-size: 0.8125rem; color: var(--slate); max-width: 26rem; }

.panel { padding: 1.25rem; border-top: 1px solid var(--hair); }
@media (min-width: 48em) { .panel { padding: 1.75rem; } }

.panel__label {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: 0.75rem;
}
.panel__count { color: var(--silver); }

/* ---------- Preview ----------
   The visitor sees the document as a document — a rendered page, a photograph —
   rather than a wall of harvested characters. For Word and plain text there is
   no page to draw, so the text itself is the honest preview. */
.preview {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
@media (min-width: 40em) {
  .preview { flex-direction: row; align-items: flex-start; gap: 1.25rem; }
}

/* One thumbnail size for every file type, so the panel does not reflow into a
   different shape depending on what was dropped. */
.preview__stage {
  flex: none;
  width: 9rem;
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: 2px;
  overflow: hidden;
  line-height: 0;
}
@media (min-width: 40em) {
  .preview__stage { width: 11rem; }
}

.preview__stage canvas,
.preview__stage img {
  display: block;
  width: 100%;
  height: auto;
}

.preview__text {
  margin-top: 1rem;
  max-height: 11rem;
  overflow-y: auto;
  padding: 0.875rem;
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.65;
  color: var(--cream-dim);
  white-space: pre-wrap;
  word-break: break-word;
  overscroll-behavior: contain;
}
@media (min-width: 40em) {
  .preview__text { max-height: 15rem; font-size: 0.8125rem; }
}

.preview__file {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0;
  min-width: 0;
}
.preview__name {
  font-size: 0.9375rem;
  color: var(--cream);
  overflow-wrap: anywhere;
}
.preview__meta {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--slate);
}

/* The line changes colour with what is crossing: silver when only text goes,
   a warmer, more emphatic tone when the file itself does. */
.will-send {
  margin: 1rem 0 0;
  font-size: 0.8125rem;
  color: var(--silver);
}
.will-send[data-mode="file"] { color: var(--silver-lit); }

/* Task chooser — a wrapping row of pills, comfortably tappable on phones. */
.tasks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  border: 0;
  padding: 0;
  margin: 0 0 1rem;
}
.tasks legend {
  padding: 0;
  margin-bottom: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
}
.task { position: relative; }
.task input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.task span {
  display: block;
  min-height: 2.5rem;
  padding: 0.6rem 0.9rem;
  font-size: 0.875rem;
  line-height: 1.3;
  color: var(--cream-dim);
  border: 1px solid var(--hair);
  border-radius: 2px;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.task input:checked + span {
  border-color: var(--silver);
  background: rgba(198, 206, 218, 0.10);
  color: var(--cream);
}
.task input:focus-visible + span { outline: 2px solid var(--silver-lit); outline-offset: 2px; }

.field { margin-bottom: 1rem; }
.field label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.875rem;
  color: var(--cream-dim);
}
.field input[type="text"] {
  width: 100%;
  min-height: 2.875rem;
  padding: 0.7rem 0.85rem;
  font-family: inherit;
  font-size: 1rem; /* 16px keeps iOS from zooming on focus */
  color: var(--cream);
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: 2px;
}
.field input::placeholder { color: var(--slate); }
.field input:focus { border-color: var(--silver); outline: none; }

/* ---------- Waiting on the model ----------
   A signet: two silver arcs turning against each other, the outer one drawing
   and undrawing as it goes. It borrows the page's own gesture — a silver line
   that draws itself — rather than importing a generic spinner. */
.result-loading {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 0;
  padding: 0.25rem 0 0.5rem;
  font-size: 0.875rem;
  color: var(--slate-lit);
}
.seal {
  width: 1.375rem;
  height: 1.375rem;
  flex: none;
  fill: none;
  stroke-linecap: round;
  overflow: visible;
}

.seal__outer,
.seal__inner {
  transform-origin: 12px 12px;
  stroke: var(--silver);
}

.seal__outer {
  stroke-width: 1.5;
  stroke-dasharray: 56.5; /* circumference at r=9 */
  animation: seal-turn 2.4s linear infinite, seal-draw 1.6s ease-in-out infinite;
}

.seal__inner {
  stroke-width: 1.1;
  stroke: var(--silver-lit);
  opacity: 0.55;
  stroke-dasharray: 26.7; /* circumference at r=4.25 */
  stroke-dashoffset: 20;
  animation: seal-turn-back 1.8s linear infinite;
}

@keyframes seal-turn { to { transform: rotate(360deg); } }
@keyframes seal-turn-back { to { transform: rotate(-360deg); } }
@keyframes seal-draw {
  0%, 100% { stroke-dashoffset: 50; }
  50%      { stroke-dashoffset: 16; }
}

/* While waiting, the empty-state line and the copy button would both be lying. */
.panel[data-busy="true"] .result:empty::after { content: none; }
.panel[data-busy="true"] .result-head .btn { visibility: hidden; }

/* Errors from the analyse action sit directly under the button that caused
   them, at a smaller size than body copy — close enough to read as feedback on
   that press, quiet enough not to shout. The icon means the message does not
   depend on colour alone. */
.field-error {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  margin: 0.75rem 0 0;
  max-width: 46ch;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--danger);
}
/* =========================================================================
   Legal page
   A page of prose, so it gets a reading measure and nothing else — no rain,
   no glow, no reveals. Terms are read when something has gone wrong, and
   nothing about that moment is improved by decoration.
   ========================================================================= */
.legal-page { background: var(--ink); }
.legal { max-width: 44rem; }
.legal h1 { margin-bottom: 0; }

.legal__section { margin-top: 2.75rem; }
.legal__section h2 {
  font-size: 1.25rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
  margin-bottom: 0.875rem;
}
@media (min-width: 48em) {
  .legal__section h2 { font-size: 1.5rem; }
}
.legal__section p {
  margin: 0 0 0.875rem;
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--cream-dim);
}
.legal__section p:last-child { margin-bottom: 0; }


/* Its own row, set off from the columns above by the rule rather than crowded
   under them. */
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.75rem;
  margin: 3.25rem 0 0;
  padding-top: 1.75rem;
  border-top: 1px solid var(--hair);
}
.footer__legal a {
  font-size: 0.8125rem;
  color: var(--silver);
  text-decoration: none;
}
.footer__legal a:hover { text-decoration: underline; }

/* =========================================================================
   Modal
   Native <dialog>: Escape, focus handling and the backdrop come for free, and
   the interruption stays escapable by every route a person might reach for.
   ========================================================================= */
.modal {
  width: min(26rem, calc(100vw - 2rem));
  padding: 1.75rem;
  color: var(--cream);
  background: var(--ink-raised);
  border: 1px solid var(--hair);
  border-radius: 4px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
}
.modal::backdrop { background: rgba(8, 8, 10, 0.72); backdrop-filter: blur(3px); }

.modal__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  color: var(--slate-lit);
  background: none;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  transition: color var(--dur) var(--ease);
}
.modal__close:hover { color: var(--cream); }
.modal__close svg { width: 1rem; height: 1rem; }

.modal__title {
  margin: 0 0 0.75rem;
  padding-right: 2rem;
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 400;
  letter-spacing: -0.015em;
}
.modal__body {
  margin: 0 0 1.5rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--cream-dim);
}
.modal__actions { display: flex; flex-wrap: wrap; gap: 0.625rem; }
.modal__actions .btn { flex: 1 1 auto; }

.upgrade {
  color: var(--gold-text);
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}
.upgrade:hover { color: var(--gold-lit); }

.field-error svg { width: 0.875rem; height: 0.875rem; flex: none; margin-top: 0.18em; }

/* =========================================================================
   Account
   ========================================================================= */
.account { position: relative; margin-left: auto; }
@media (min-width: 48em) { .account { margin-left: 0; } }

/* Struck in the same metal as the headline and the primary action, one size
   down. Signing in belongs with the page's actions, not its quiet furniture. */
.account__btn {
  min-height: 2.25rem;
  padding: 0.4rem 0.9rem;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink);
  background: var(--gold-sheen);
  background-size: 100% 100%;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-size 420ms var(--ease), transform 120ms var(--ease);
}
.account__btn:hover { background-size: 140% 140%; }
.account__btn:active { transform: translateY(1px); }

.account__panel {
  position: absolute;
  top: calc(100% + 0.625rem);
  right: 0;
  z-index: 60;
  width: min(20rem, calc(100vw - 2rem));
  padding: 1.25rem;
  background: var(--ink-raised);
  border: 1px solid var(--hair);
  border-radius: 3px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
}

.account__panel label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.8125rem;
  color: var(--cream-dim);
}
.account__panel input[type="email"] {
  width: 100%;
  min-height: 2.875rem;
  margin-bottom: 0.75rem;
  padding: 0.7rem 0.85rem;
  font-family: inherit;
  font-size: 1rem; /* 16px keeps iOS from zooming on focus */
  color: var(--cream);
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: 2px;
}
.account__panel input:focus { border-color: var(--silver); outline: none; }
.account__panel .btn { width: 100%; }

.account__hint {
  margin: 0.875rem 0 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--slate);
}
.account__msg {
  margin: 0.875rem 0 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--silver);
}
.account__msg[data-tone="error"] { color: var(--danger); }
.account__msg[data-tone="ok"] { color: var(--gold-text); }

.account__email { margin: 0 0 0.25rem; font-size: 0.875rem; overflow-wrap: anywhere; }
.account__plan {
  margin: 0 0 1rem;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-text);
}

/* =========================================================================
   Plans
   ========================================================================= */
.cycle {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.25rem;
  margin-bottom: 2rem;
  border: 1px solid var(--hair);
  border-radius: 3px;
}
.cycle__btn {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  min-height: 2.25rem;
  padding: 0.45rem 0.9rem;
  font-family: inherit;
  font-size: 0.875rem;
  color: var(--slate-lit);
  background: none;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.cycle__btn[aria-pressed="true"] { background: var(--ink-raised); color: var(--cream); }
.cycle__btn em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.plans {
  display: grid;
  gap: 1rem;
}
@media (min-width: 56em) {
  .plans { grid-template-columns: repeat(3, 1fr); gap: 1.25rem; align-items: start; }
}

.plan {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  background: var(--ink-raised);
  border: 1px solid var(--hair);
  border-radius: 3px;
}
/* The middle tier carries the one gold edge — the same reserve as the rest of
   the page, spent on the plan we expect most people to want. */
.plan--featured { border-color: rgba(212, 181, 112, 0.45); }

.plan__name {
  margin: 0 0 0.875rem;
  font-family: var(--font-display);
  font-size: 1.25rem;
}

.plan__price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0 0 1.25rem;
}
.plan__price b {
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.02em;
}
.plan__price span { font-size: 0.875rem; color: var(--slate-lit); }
.plan__price em {
  flex-basis: 100%;
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--slate);
}

.plan__rows { margin: 0 0 1.5rem; flex: 1; }
.plan__rows > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.625rem 0;
  border-top: 1px solid var(--hair);
  font-size: 0.875rem;
}
.plan__rows dt { color: var(--slate-lit); }
.plan__rows dd { margin: 0; text-align: right; color: var(--cream); }

.plan__cta { width: 100%; margin: 0; }
.plan__cta--current {
  padding: 0.75rem 0;
  text-align: center;
  font-size: 0.875rem;
  color: var(--slate);
  border: 1px solid var(--hair);
  border-radius: 2px;
}


/* =========================================================================
   Analyst mode
   ========================================================================= */
.quota {
  margin: 1.25rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
}
.quota[data-state="empty"] { color: var(--danger); text-transform: none; letter-spacing: 0.02em; }

/* The schema is the honest preview for a dataset: these column names, and
   nothing else about the contents, are what the model is shown. */
.schema {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  max-height: 8rem;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.schema__col {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.3rem 0.55rem;
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: 2px;
  font-size: 0.75rem;
}
.schema__col b { font-weight: 500; color: var(--cream); }
.schema__col i {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  color: var(--slate);
}

.thread { display: flex; flex-direction: column; gap: 1.5rem; margin-top: 1.5rem; }
.thread:empty { margin-top: 0; }

.turn {
  padding-top: 1.25rem;
  border-top: 1px solid var(--hair);
}
.turn__q {
  margin: 0 0 0.75rem;
  font-size: 0.9375rem;
  color: var(--silver);
}
.turn__q::before { content: "— "; color: var(--slate); }

.turn__status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.875rem;
  color: var(--slate-lit);
}

.turn__a {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.7;
  white-space: pre-wrap;
}

.turn__empty {
  margin: 0.75rem 0 0;
  font-size: 0.875rem;
  color: var(--slate);
}

.turn__table {
  margin-top: 1rem;
  overflow-x: auto;
  border: 1px solid var(--hair);
  border-radius: 2px;
}
.turn__table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
}
.turn__table th,
.turn__table td {
  padding: 0.5rem 0.75rem;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--hair);
}
.turn__table th {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--slate);
  background: var(--ink-sunk);
}
.turn__table td { color: var(--cream-dim); }
.turn__table tr:last-child td { border-bottom: 0; }


/* Openings the model drew from this particular table. */
.suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}
.suggestion {
  padding: 0.5rem 0.75rem;
  font-family: inherit;
  font-size: 0.8125rem;
  line-height: 1.3;
  text-align: left;
  color: var(--cream-dim);
  background: none;
  border: 1px solid var(--hair);
  border-radius: 2px;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.suggestion::before { content: "↳ "; color: var(--slate); }
.suggestion:hover { border-color: var(--silver); color: var(--cream); }

/* How much room is left in this conversation. The bar is the measure; the text
   says it in words for anyone who cannot see the bar. */
.context {
  position: relative;
  margin: 1.5rem 0 0;
  padding-top: 0.625rem;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--warn);
}
.context::before,
.context::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 2px;
  border-radius: 1px;
}
.context::before { width: 100%; background: var(--hair); }
/* The bar fills as the conversation is spent, matching the wording. */
.context::after {
  width: var(--used, 0%);
  background: var(--warn);
  transition: width 420ms var(--ease), background var(--dur) var(--ease);
}
.context[data-state="low"]::after { background: var(--gold); }
.context[data-state="empty"] { color: var(--danger); text-transform: none; letter-spacing: 0.02em; }
.context[data-state="empty"]::after { background: var(--danger); width: 100%; }

.ask {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin-top: 1.5rem;
}
@media (min-width: 40em) {
  .ask { flex-direction: row; }
  .ask input { flex: 1; }
}
.ask input {
  min-height: 2.875rem;
  padding: 0.7rem 0.85rem;
  font-family: inherit;
  font-size: 1rem; /* 16px keeps iOS from zooming on focus */
  color: var(--cream);
  background: var(--ink-sunk);
  border: 1px solid var(--hair);
  border-radius: 2px;
}
.ask input::placeholder { color: var(--slate); }
.ask input:focus { border-color: var(--silver); outline: none; }
.ask input:disabled { opacity: 0.5; }

.result {
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--cream);
  white-space: pre-wrap;
  word-break: break-word;
}
.result:empty::after {
  content: attr(data-empty);
  color: var(--slate);
  font-size: 0.875rem;
}

.result-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.875rem;
}

.status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--slate-lit);
}
.status[data-tone="error"] { color: var(--danger); }

.spinner {
  width: 0.875rem; height: 0.875rem;
  border: 1.5px solid var(--hair);
  border-top-color: var(--silver);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
  flex: none;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Commitments ---------- */
.commitments {
  display: grid;
  gap: 0;
}
@media (min-width: 48em) {
  .commitments { grid-template-columns: 1fr 1fr; gap: 0 3rem; }
}

.commitment {
  position: relative;
  padding-block: 1.375rem;
}
.commitment h3 {
  display: flex;
  align-items: baseline;
  gap: 0.625rem;
  margin-bottom: 0.375rem;
}
.commitment h3::before {
  content: "";
  flex: none;
  width: 0.375rem; height: 0.375rem;
  border-radius: 50%;
  background: var(--silver);
  transform: translateY(-0.15em);
}
.commitment p {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--slate-lit);
  line-height: 1.6;
}

/* ---------- Footer ---------- */
.footer {
  border-top: 1px solid var(--hair);
  padding-block: 2.5rem;
}
@media (min-width: 48em) { .footer { padding-block: 3.5rem; } }

.footer__grid {
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}
@media (min-width: 48em) {
  .footer__grid {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
    gap: 3rem;
  }
}

.footer__tagline {
  font-family: var(--font-display);
  font-size: 1.125rem;
  line-height: 1.3;
  max-width: 22ch;
  margin: 0.5rem 0 0;
}

.footer__meta {
  margin: 1.125rem 0 0;
  font-size: 0.8125rem;
  color: var(--slate);
  text-align: center;
}

.footer__label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: 0.625rem;
}
.footer .lang a { padding-left: 0; }

.footer__address {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-style: normal;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--cream-dim);
}
.footer__address a {
  color: var(--silver);
  text-decoration: none;
  width: fit-content;
  transition: color var(--dur) var(--ease);
}
.footer__address a:hover { color: var(--silver-lit); text-decoration: underline; }

/* Icon only — the profile URL is never shown as text. */
.footer__social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  margin: 0.875rem 0 0 -0.4rem;
  border-radius: 2px;
  color: var(--slate-lit);
  transition: color var(--dur) var(--ease);
}
.footer__social svg { width: 1.125rem; height: 1.125rem; }
.footer__social:hover { color: var(--silver-lit); }

/* ---------- Scroll reveal ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* =========================================================================
   Drawn rules
   One motion idea, used everywhere a hairline appears: the line draws itself
   from the left as it enters. Section dividers, card rules and the ghost
   button fill all obey it, so the page reads as one hand rather than a
   collection of effects. Only transform is animated — no layout work.
   ========================================================================= */
.step::before,
.commitment::before,
.divider span {
  content: "";
  display: block;
  height: 1px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms var(--ease);
}

.step::before,
.commitment::before {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background: var(--hair);
  transition-delay: 140ms;
}
.step.is-in::before,
.commitment.is-in::before { transform: scaleX(1); }

/* Section dividers sit between the major blocks. They are silver, but they
   fade out to the right so they stay quieter than the boundary rule — the
   boundary is the signature and has to remain the loudest line on the page. */
.divider {
  width: 100%;
  max-width: 76rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.divider span {
  background: linear-gradient(90deg,
    var(--silver) 0%,
    rgba(198, 206, 218, 0.35) 45%,
    rgba(198, 206, 218, 0.08) 100%);
  transition-duration: 1100ms;
}
.divider.is-in span { transform: scaleX(1); }

/* Hovering shifts the highlight across the metal instead of moving the button. */
.btn--primary { transition: background-size 420ms var(--ease), transform 120ms var(--ease); }

/* =========================================================================
   Cursor glow — "How it works" only
   A soft silver field that trails the pointer, lagging just behind it. Pointer
   devices only: on a touch screen there is no cursor to follow, and the effect
   would just be a smear under the thumb.
   ========================================================================= */
.glow-field { position: relative; overflow: hidden; }
.glow-field > .shell { position: relative; z-index: 1; }

.glow {
  position: absolute;
  top: 0;
  left: 0;
  width: 34rem;
  height: 34rem;
  margin: -17rem 0 0 -17rem;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle closest-side,
    rgba(198, 206, 218, 0.14),
    rgba(198, 206, 218, 0.05) 42%,
    transparent 72%);
  transition: opacity 700ms var(--ease);
  will-change: transform;
}
.glow-field[data-glow="on"] .glow { opacity: 1; }

@media (hover: none), (pointer: coarse) {
  .glow { display: none; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal-word { opacity: 1; transform: none; }
  [data-reveal] { opacity: 1; transform: none; }
  .step::before,
  .commitment::before,
  .divider span { transform: scaleX(1); }
  .glow { display: none; }
  /* The seal keeps turning — it is the only signal that work is in progress —
     but slowly, and without the drawing pulse. */
  .seal__outer {
    animation: seal-turn 4s linear infinite !important;
    stroke-dashoffset: 16;
  }
  .seal__inner { animation: none !important; }
}
