/* ==========================================================================
   Clara site — layout and page styling.
   Every color and type decision references a token or a named class from
   tokens.css. There is exactly one raw color in this file, and it is
   commented where it appears.
   ========================================================================== */

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

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

body {
  margin: 0;
  background: var(--clara-background);
  color: var(--clara-primary-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ---- Layout primitives ---------------------------------------------- */

:root {
  /* Asymmetric rhythm: all the air sits ABOVE a section, none below it. A
     title is then bound to the content it introduces rather than floating
     equidistant between two sections. The next section's top padding does
     the separating. */
  --section-top: 140px;
  --container-pad: 28px;
  /* The page's one divider device. */
  --rule-length: 44px;
}

@media (max-width: 700px) {
  :root {
    --section-top: 84px;
  }
}

@media (max-width: 600px) {
  :root {
    --container-pad: 20px;
  }
}

.container {
  max-width: 1080px;
  margin-inline: auto;
  padding-inline: var(--container-pad);
}

/* Off-screen but available to screen readers — used for the form labels. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Sections -------------------------------------------------------- */

/* No rules between sections. A hairline above every section is a generic
   broadsheet device; spacing separates them better and leaves the one short
   rule below meaning something. */
.section > .container {
  padding-top: var(--section-top);
  padding-bottom: 0;
}

.section h2,
.section p,
.section ul {
  margin: 0;
}

/* Rhythm inside a section. These four rules govern every section on the page;
   there are no per-section margin overrides. */
.section__eyebrow {
  margin: 0 0 20px;
}

.section__title {
  margin: 0 0 34px;
  max-width: var(--clara-measure-title);
}

/* The page's only divider: a short rule, 40px above the closing statement,
   28px below it. Drawn as a pseudo-element so the statement owns its own
   spacing and nothing has to be threaded through the markup. */
.section__statement {
  position: relative;
  margin-top: 40px;
  padding-top: 29px; /* 1px rule + 28px */
}

.section__statement::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: var(--rule-length);
  height: 1px;
  background: var(--clara-tile-border);
}

/* ---- Measure --------------------------------------------------------- */

/* Unconstrained, this copy runs past 90 characters per line. Every text block
   on the page is capped. */
.section__prose {
  max-width: var(--clara-measure-display);
}

.section__note {
  max-width: var(--clara-measure-ui);
}

.section__prose + .section__note {
  margin-top: 28px;
}

/* ---- Hero ------------------------------------------------------------ */

.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: max(88vh, 640px);
  /* Painted before the poster resolves, so there is never a white or black
     flash on first paint. */
  background-color: var(--clara-background);
}

@supports (height: 88svh) {
  .hero {
    min-height: max(88svh, 640px);
  }
}

/* ---- Hero layer 1: video --------------------------------------------- */

.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* cover is what prevents letterboxing when the viewport aspect ratio does
     not match the footage's 16:9. */
  object-fit: cover;
  /* Centre is deliberate: on a narrow phone viewport the crop keeps the
     television, which carries the most legible signal in the clip — the
     screen going black. The trade-off is that the lamp on the right edge is
     cropped out on very narrow screens. Accepted here rather than solved
     with art-directed sources. */
  object-position: center;
}

/* ---- Hero layer 2: scrim --------------------------------------------- */

/* The video swings dramatically in brightness across its six seconds, so a
   fixed scrim cannot serve both ends: tuned for the dark ending it leaves the
   headline unreadable over the bright opening; tuned for the opening it turns
   the settled room to mud. So the scrim adapts, lightening on the same curve
   as the room dims, which keeps perceived text contrast roughly constant. */
:root {
  /* The one scrim color. This is --clara-background (#1C1A17) written as RGB
     channels so the same color can be carried at several alphas below — a
     custom property cannot hold a variable alpha any other way. Besides the
     Decompress veil, this is the only literal color in this file. */
  --clara-scrim: 28 26 23;

  /* Heavy default — the fail-safe. Must clear the brightest frame. */
  --clara-scrim-heavy: rgb(var(--clara-scrim) / 0.74);
  /* Settled — lets the warm room read through once it has gone dark. */
  --clara-scrim-settled: rgb(var(--clara-scrim) / 0.52);
  /* Edge weighting, applied in both states. */
  --clara-scrim-edge: rgb(var(--clara-scrim) / 0.2);
  /* Matches the clip length, so the scrim lifts as the room dims. */
  --clara-hero-scrim-fade: 6s;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  /* Must never intercept a click on the form. */
  pointer-events: none;
  /* Heavy by default and deliberately so: if the video never loads, never
     autoplays, or is disabled outright, the scrim stays strong over the
     bright poster and the copy is still readable. It lightens only once
     playback has actually started. */
  background-color: var(--clara-scrim-heavy);
  /* Heavier at the top and bottom edges in both states: the copy and form sit
     on denser ground, and the hero blends into the section below instead of
     ending on a hard line. Composites to ~0.79 alpha at the edges when heavy,
     ~0.62 when settled. */
  background-image: linear-gradient(
    to bottom,
    var(--clara-scrim-edge) 0%,
    transparent 30%,
    transparent 70%,
    var(--clara-scrim-edge) 100%
  );
  transition: background-color var(--clara-hero-scrim-fade)
    var(--clara-motion-dimmer-ease);
}

/* Playback has begun — ride the room down. */
.hero.is-playing .hero__scrim {
  background-color: var(--clara-scrim-settled);
}

/* Playback finished, or we are showing a still. Pins the settled value
   authoritatively so a paused or stalled fade cannot strand the scrim
   half-lit; the shorter duration converges quickly without snapping. */
.hero.is-settled .hero__scrim {
  background-color: var(--clara-scrim-settled);
  transition-duration: var(--clara-motion-dimmer);
}

/* ---- Hero layer 3: content ------------------------------------------- */

.hero > .container {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-block: var(--section-top);
}

/* ---- Hero still fallback --------------------------------------------- */

/* Applied by waitlist.js for Save-Data and for blocked autoplay. The still is
   the CALM final frame, not the poster: the poster is the bright "before"
   frame, and stranding someone there shows the wrong room. The
   prefers-reduced-motion block at the end of this file does the same thing
   without needing JS. */
.hero.is-still {
  background-image: url('../video/landingvid-calm.jpg');
  background-size: cover;
  background-position: center;
}

.hero.is-still .hero-video {
  display: none;
}

.hero__eyebrow {
  margin: 0 0 18px;
}

.hero__title {
  margin: 0 0 24px;
  max-width: 18ch;
}

/* Tighter than --clara-measure-display: this sits over video, where a short
   line is easier to hold than a long one. */
.hero__prose {
  margin: 0 0 36px;
  max-width: 42ch;
}

.hero__note {
  margin: 14px 0 0;
}

/* ---- Waitlist form (used in both the hero and the close) -------------- */

.waitlist {
  max-width: 520px;
}

.waitlist__row {
  display: flex;
  gap: 12px;
  align-items: stretch;
}

.waitlist__input {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--clara-tile-surface);
  border: 1px solid var(--clara-tile-border);
  border-radius: 10px;
  padding: 14px 16px;
  /* text-align IS inherited, so the centred close section would otherwise
     centre the typed address. */
  text-align: left;
  /* Type comes from .clara-row-label in the markup; inputs do not inherit
     font by default, so the class carries family/size/weight/color. */
  transition: border-color 0.18s ease;
}

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

.waitlist__input:focus {
  border-color: var(--clara-amber-accent);
}

/* The hero form sits over video, so a border-color change alone is not
   enough — on a bright frame it disappears. The amber ring carries a solid
   background-colored halo behind it, which keeps the focus state legible
   whatever the footage is doing underneath. */
.waitlist__input:focus-visible,
.waitlist__button:focus-visible {
  outline: 3px solid var(--clara-amber-accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 8px var(--clara-background);
}

/* Amber-on-amber would vanish against the button's own fill. */
.waitlist__button:focus-visible {
  outline-color: var(--clara-primary-text);
}

/* AUTOFILL — WORKAROUND, NOT A DESIGN CHOICE. DO NOT "CLEAN UP".
   Chrome and Safari paint their own pale background on an autofilled input and
   ignore `background-color` outright, so the email field renders white against
   a dark page. A 1000px inset box-shadow is the only reliable override: it
   fills the padding box with a color we choose. `color` is ignored on
   autofilled text for the same reason, hence -webkit-text-fill-color. The
   absurd transition duration parks the browser's yellow autofill flash
   somewhere it will never arrive. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px var(--clara-tile-surface) inset;
  -webkit-text-fill-color: var(--clara-primary-text);
  caret-color: var(--clara-primary-text);
  transition: background-color 9999s ease-in-out 0s;
}

/* The rule above sets box-shadow, which is exactly what the hero's focus halo
   uses — left alone it would swallow that halo on an autofilled field, over
   video, where it is needed most. Restated here with both shadows so the
   autofilled state keeps the full focus treatment. The amber outline and the
   border color survive on their own: neither is a box-shadow. */
.waitlist__input:-webkit-autofill:focus-visible {
  -webkit-box-shadow: 0 0 0 1000px var(--clara-tile-surface) inset,
    0 0 0 8px var(--clara-background);
}

.waitlist__button {
  flex: 0 0 auto;
  background: var(--clara-amber-accent);
  border: 1px solid var(--clara-amber-accent);
  border-radius: 10px;
  padding: 14px 22px;
  cursor: pointer;
  /* Label type comes from .clara-on-accent in the markup. */
  transition: filter 0.18s ease;
}

.waitlist__button:hover {
  filter: brightness(1.08);
}

.waitlist__button[disabled] {
  opacity: 0.6;
  cursor: default;
  filter: none;
}

/* Honeypot. Positioned off-canvas rather than display:none or
   visibility:hidden — bots commonly skip fields hidden those ways, which is
   exactly the population this field exists to catch. The input inside is
   tabindex="-1" and the wrapper is aria-hidden, so it is unreachable by
   keyboard and silent to screen readers. */
.waitlist__honeypot {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Reserved height so a status message does not shift the layout. */
.waitlist__status {
  margin: 10px 0 0;
  min-height: calc(13px * var(--clara-line-tight));
}

.waitlist__status--success {
  color: var(--clara-sage-accent);
}

@media (max-width: 560px) {
  .waitlist,
  .waitlist__row {
    max-width: none;
  }

  .waitlist__row {
    flex-direction: column;
  }

  .waitlist__button {
    width: 100%;
  }
}

/* ---- Signature moment: the Decompress dim ---------------------------- */

.decompress {
  position: relative;
  isolation: isolate;
  /* Was 0.55. Narrowed substantially once the hero gained video: the hero now
     performs the dim as the visitor arrives, so repeating it at full strength
     here reads as the same trick twice. Kept as a quiet reinforcement —
     present, felt, no longer a second performance. */
  opacity: 0.88;
  transition: opacity var(--clara-motion-dimmer) var(--clara-motion-dimmer-ease);
}

.decompress__veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* The one intentional off-token value on the page: a shade deeper than
     --clara-background so the section reads as the room dimming. It exists
     only as this veil and is never used as a text or surface color. */
  background: #151312;
  opacity: 0;
  transition: opacity var(--clara-motion-dimmer) var(--clara-motion-dimmer-ease);
}

.decompress .section__eyebrow {
  opacity: 0;
  transition: opacity var(--clara-motion-glow-bloom) var(--clara-motion-glow-ease)
    var(--clara-motion-stagger);
}

.decompress.is-lit,
.decompress.is-lit .decompress__veil,
.decompress.is-lit .section__eyebrow {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  /* Animated background video is a known vestibular trigger, so this path is
     a requirement rather than polish. The visitor gets the calm end state as
     a still — the composition we actually want to show, not the bright
     "before" frame. Handled in CSS rather than JS so it holds even if JS
     never runs. */
  .hero-video {
    display: none;
  }

  .hero {
    background-image: url('../video/landingvid-calm.jpg');
    background-size: cover;
    background-position: center;
  }

  /* Pinned at settled, no fade — the still is already the dark room. */
  .hero__scrim {
    background-color: var(--clara-scrim-settled);
    transition: none;
  }

  .decompress,
  .decompress__veil,
  .decompress .section__eyebrow {
    transition: none;
  }

  /* Reduced-motion visitors get the final state immediately. */
  .decompress,
  .decompress .section__eyebrow {
    opacity: 1;
  }

  .decompress__veil {
    opacity: 1;
  }
}

/* ---- Decompress composition ------------------------------------------ */

/* The copy was always a sequence; as one paragraph that was hidden. One beat
   per line lets the eye move down it.

   Wider than --clara-measure-display by necessity: the longest beat is 60
   characters, and one-beat-per-line is the entire point of the block. Below
   that width the beats wrap, which is unavoidable on a phone. */
.decompress__beats {
  max-width: 62ch;
}

.decompress__beat {
  display: block;
}

.decompress__reflection {
  margin-top: 28px;
  max-width: var(--clara-measure-display);
}

/* ---- How it works: two columns --------------------------------------- */

.conducts__grid {
  display: grid;
  /* 58fr + 34fr against an 8% gap resolves to exactly 58% / 34%. */
  grid-template-columns: 58fr 34fr;
  column-gap: 8%;
  align-items: start;
}

@media (max-width: 860px) {
  .conducts__grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 48px;
  }
}

/* Set as a list the brands read as capability; buried in a sentence they read
   as a short list. Text only — no logos. */
.conducts__list {
  list-style: none;
  padding: 0;
}

.conducts__item {
  padding-block: 14px;
  border-bottom: 1px solid var(--clara-tile-border);
}

.conducts__more {
  margin-top: 20px;
}

/* ---- What this replaces: two contrasting blocks ---------------------- */

.replaces__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 8%;
  align-items: start;
}

@media (max-width: 700px) {
  .replaces__grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 48px;
  }
}

.replaces__heading {
  margin: 0 0 24px;
}

.replaces__line + .replaces__line {
  margin-top: 16px;
}

/* The whole device is the color difference: the dealer column recedes into
   secondary text, the Clara column holds primary. No borders, backgrounds,
   cards, checkmarks, or crosses. */
.replaces__block--muted .replaces__heading,
.replaces__block--muted .replaces__line {
  color: var(--clara-secondary-text);
}

.replaces__grid + .section__note {
  margin-top: 48px;
}

/* ---- Centred sections: Local first, Close ---------------------------- */

/* This is a principle, not a feature — the most air and the least
   structure. */
.section--center {
  text-align: center;
}

.section--center .section__title,
.section--center .section__prose,
.section--center .close__title,
.section--center .waitlist {
  margin-inline: auto;
}

/* ---- Close ----------------------------------------------------------- */

.close__title {
  margin: 0 0 34px;
}

/* ---- Links ----------------------------------------------------------- */

/* Color is inherited from whichever type class the anchor carries, so a link
   never breaks the voice of the text around it; the hairline is what marks it
   as a link. */
a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--clara-tile-border);
  transition: border-color 0.18s ease;
}

a:hover {
  border-bottom-color: var(--clara-amber-accent);
}

a:focus-visible {
  outline: 2px solid var(--clara-amber-accent);
  outline-offset: 3px;
}

/* ---- Privacy page ---------------------------------------------------- */

/* privacy.html reuses the page's type styles wholesale. All this adds is a
   narrow centred column and the rhythm between blocks — no new type, no new
   color, no new surface. */
.legal {
  max-width: var(--clara-measure-ui);
  margin-inline: auto;
}

.legal p {
  margin: 0;
}

.legal p + p {
  margin-top: 16px;
}

.legal__title {
  margin: 0 0 34px;
}

.legal__heading {
  margin: 40px 0 12px;
}

.legal__updated {
  margin-top: 56px;
}

.legal__back {
  display: inline-block;
  margin-top: 12px;
}

/* ---- Footer ---------------------------------------------------------- */

.footer > .container {
  padding-top: var(--section-top);
  padding-bottom: calc(var(--section-top) / 2);
}

.footer p {
  margin: 0;
}
