/* ---------------------------------------------------------------
   PRESSA — colourway-synced hero
   The whole page is themed from one variable, --bg, set by app.js.
   Everything that changes colour transitions on the same curve, so
   the background, the shadow and the chrome all arrive together.
   --------------------------------------------------------------- */

/* Registering --bg as a real <color> is what makes the backdrop tween.
   background-image is not an animatable property, so a gradient can't be
   transitioned directly — but a registered custom property can, and every
   gradient stop below is derived from it, so the whole lit backdrop
   re-renders each frame as --bg interpolates. */
@property --bg {
  syntax: "<color>";
  inherits: true;
  initial-value: #d24105;
}

/* Text colour is per-colourway: a backdrop light enough to feel airy can't
   carry white type. --paper is its opposite, used for the translucent
   panels behind the nav and icon buttons so they always sit against the
   text rather than with it. */
@property --ink {
  syntax: "<color>";
  inherits: true;
  initial-value: #ffffff;
}

@property --paper {
  syntax: "<color>";
  inherits: true;
  initial-value: #000000;
}

:root {
  --bg: #d24105;
  --ink: #ffffff;
  --paper: #000000;

  /* Tweened at the source so the backdrop and every text colour arrive
     together; descendants inherit the values mid-animation. */
  transition:
    --bg var(--dur-bg) var(--ease),
    --ink var(--dur-bg) var(--ease),
    --paper var(--dur-bg) var(--ease);

  --ease: cubic-bezier(.65, .02, .28, 1);
  --dur-bg: 900ms;
  --dur-fade: 780ms;

  --pad-x: clamp(20px, 3.6vw, 56px);
  --pad-y: clamp(18px, 2.6vh, 34px);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

/* Type scale — each step ~1.27x the last, so sizes read as distinct levels
   rather than four near-identical greys of text.
   11 → 14 → 18 → 23, then fluid clamps above that for display sizes. */
body {
  font-family: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Explicit base, otherwise anything unstyled sits at the browser's 16px
     and lands between two steps of the scale. */
  font-size: 18px;
  color: var(--ink);
  background-color: var(--bg);
  overflow: hidden;
}

/* The stage carries the themed backdrop; --bg tweens on :root and is
   inherited here, so the whole thing animates from one value.

   Both gradients run on many stops rather than two. A two-stop ramp to
   transparent interpolates linearly and leaves a visible ring where the
   falloff ends — these approximate an eased curve so the light dissolves
   into the background with no edge to catch. */
.stage {
  position: relative;
  height: 100%;
  min-height: 640px;
  display: grid;
  grid-template-rows: auto 1fr auto;

  background-color: var(--bg);
  background-image:
    /* the lit pool the product stands in */
    radial-gradient(58% 62% at 50% 45%,
      rgba(255, 255, 255, .150) 0%,
      rgba(255, 255, 255, .132) 12%,
      rgba(255, 255, 255, .108) 24%,
      rgba(255, 255, 255, .082) 36%,
      rgba(255, 255, 255, .057) 48%,
      rgba(255, 255, 255, .036) 60%,
      rgba(255, 255, 255, .020) 71%,
      rgba(255, 255, 255, .009) 82%,
      rgba(255, 255, 255, .002) 92%,
      rgba(255, 255, 255, 0) 100%),
    /* Fill light gathering in each corner, so the frame doesn't just get
       darker and darker outward — the eye reads two light sources rather
       than one spotlight in a black box. Painted above the vignette. */
    radial-gradient(48% 52% at 0% 0%,
      rgba(255, 255, 255, .070) 0%,
      rgba(255, 255, 255, .052) 24%,
      rgba(255, 255, 255, .031) 46%,
      rgba(255, 255, 255, .014) 66%,
      rgba(255, 255, 255, .004) 82%,
      rgba(255, 255, 255, 0) 94%),
    radial-gradient(48% 52% at 100% 0%,
      rgba(255, 255, 255, .070) 0%,
      rgba(255, 255, 255, .052) 24%,
      rgba(255, 255, 255, .031) 46%,
      rgba(255, 255, 255, .014) 66%,
      rgba(255, 255, 255, .004) 82%,
      rgba(255, 255, 255, 0) 94%),
    radial-gradient(48% 52% at 0% 100%,
      rgba(255, 255, 255, .058) 0%,
      rgba(255, 255, 255, .043) 24%,
      rgba(255, 255, 255, .026) 46%,
      rgba(255, 255, 255, .012) 66%,
      rgba(255, 255, 255, .003) 82%,
      rgba(255, 255, 255, 0) 94%),
    radial-gradient(48% 52% at 100% 100%,
      rgba(255, 255, 255, .058) 0%,
      rgba(255, 255, 255, .043) 24%,
      rgba(255, 255, 255, .026) 46%,
      rgba(255, 255, 255, .012) 66%,
      rgba(255, 255, 255, .003) 82%,
      rgba(255, 255, 255, 0) 94%),
    /* The falloff between the two — deepest in the mid-ring, easing back
       at the very edge so the corners can catch their own light. */
    radial-gradient(116% 110% at 50% 45%,
      rgba(0, 0, 0, 0) 22%,
      rgba(0, 0, 0, .016) 34%,
      rgba(0, 0, 0, .046) 46%,
      rgba(0, 0, 0, .090) 57%,
      rgba(0, 0, 0, .140) 67%,
      rgba(0, 0, 0, .180) 76%,
      rgba(0, 0, 0, .196) 84%,
      rgba(0, 0, 0, .186) 92%,
      rgba(0, 0, 0, .166) 100%);
}

/* Dither.

   The halo is smooth in maths but not on screen: 8-bit colour can only step
   1/255 at a time, and across ~900px of a gentle ramp each step spans tens
   of pixels — which is what reads as concentric rings. No number of gradient
   stops fixes that; the steps are a quantisation limit, not a curve problem.
   A film grain of noise breaks the step edges up so the eye integrates them
   back into a continuous ramp. Same trick as dithering an audio fade. */
.stage::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: .055;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

svg {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ------------------------------ top bar ------------------------ */

.topbar {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: var(--pad-y) var(--pad-x);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: inherit;
}

.brand__mark {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--ink);
  color: var(--bg);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .04em;
  transition: color var(--dur-bg) var(--ease);
}

.brand__word {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
}

.nav {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 26%, transparent);
  backdrop-filter: blur(6px);
}

.nav__link {
  padding: 9px 17px;
  border-radius: 999px;
  color: color-mix(in srgb, var(--ink) 88%, transparent);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color 220ms ease, background-color 220ms ease;
}

.nav__link:hover { color: var(--ink); }

.nav__link.is-current {
  color: var(--bg);
  background: var(--ink);
  transition: color var(--dur-bg) var(--ease), background-color 220ms ease;
}

.utils {
  display: flex;
  gap: 10px;
}

.icon-btn {
  width: 36px;
  height: 36px;
  padding: 9px;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--paper) 26%, transparent);
  color: var(--ink);
  cursor: pointer;
  transition: background-color 220ms ease, transform 220ms ease;
}

.icon-btn:hover {
  background: color-mix(in srgb, var(--paper) 42%, transparent);
  transform: translateY(-1px);
}

/* ------------------------------- hero -------------------------- */

.hero {
  position: relative;
  z-index: 2;
  display: grid;
  /* Side tracks are equal so the centre track — and the product in it —
     lands on the viewport centre, as in the reference. */
  grid-template-columns: minmax(260px, 1fr) minmax(0, 1.5fr) minmax(200px, 1fr);
  align-items: center;
  gap: clamp(16px, 3vw, 48px);
  padding: 0 var(--pad-x);
  min-height: 0;
}

.col--left  { max-width: 430px; }
.col--right { justify-self: end; text-align: right; }

.pager {
  display: flex;
  gap: 10px;
  margin-bottom: clamp(18px, 4vh, 44px);
}

.pager__btn {
  width: 34px;
  height: 34px;
  padding: 8px;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--paper) 26%, transparent);
  color: var(--ink);
  cursor: pointer;
  transition: background-color 220ms ease, transform 220ms ease;
}

.pager__btn:hover {
  background: color-mix(in srgb, var(--paper) 45%, transparent);
  transform: scale(1.06);
}

/* Display face. Instrument Serif carries the editorial weight a premium
   appliance wants; the sans does the working text. Two families with real
   contrast between them beats one family doing both jobs. */
.headline,
.page-title,
.price__now {
  font-family: "Bodoni Moda", ui-serif, Georgia, serif;
  font-weight: 400;
  letter-spacing: -.01em;
}

.headline {
  margin: 0 0 22px;
  font-size: clamp(42px, 5.6vw, 82px);
  /* Serif descenders need more room than the old grotesque did. */
  line-height: 1.0;
}

.blurb {
  margin: 0 0 clamp(20px, 4vh, 38px);
  max-width: 40ch;
  font-size: 14px;
  line-height: 1.72;
  color: var(--ink);
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 13px 15px 13px 25px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .08em;
  text-decoration: none;
  transition: color var(--dur-bg) var(--ease), transform 260ms var(--ease);
}

.cta svg { width: 17px; height: 17px; stroke-width: 1.9; }
.cta:hover { transform: translateX(4px); }

/* ----------------------------- machine ------------------------- */

.col--stage {
  position: relative;
  height: 100%;
  display: grid;
  place-items: center;
  min-height: 0;
  overflow: visible;
}

/* Matches the render's own 3:2 ratio so `contain` adds no letterboxing —
   otherwise the box is taller than the image and the shadow below detaches
   from the feet. About 36% of each render is transparent side padding, so
   the box can overflow its grid column without the machine colliding with
   anything. */
.machine {
  position: relative;
  /* Front-on renders: the subject fills ~96% of the box height but only
     ~67% of its width, so the box is wider than the machine looks. Sized
     so the product stands about 45% of viewport height, as in the
     reference. */
  width: min(30vw, 420px);
  max-height: 56vh;
  aspect-ratio: 1322 / 1190;
  margin-inline: auto;
  transform-origin: 50% 62%;
  transition: transform 620ms var(--ease);
}

/* Drawn, not baked — so it tints with whatever the background becomes. */
.machine__shadow {
  position: absolute;
  left: 50%;
  bottom: 0.5%;
  width: 52%;
  height: 4.5%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,.55), rgba(0,0,0,0) 70%);
  mix-blend-mode: multiply;
  transition: opacity 620ms var(--ease);
}

/* Resting state only. The diagonal travel is driven by the Web Animations
   API in app.js so the incoming and outgoing renders can follow different
   paths on the same clock. */
.machine__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

.machine__img.is-active { opacity: 1; }

/* The incoming render travels over the outgoing one. */
.machine__img.is-entering { z-index: 2; }
.machine__img.is-leaving  { z-index: 1; }

/* The shadow belongs to whichever render is standing in the hero spot, so
   it lifts while both are in the air and returns as the new one lands. */
.machine.is-switching .machine__shadow { opacity: 0; }

/* ------------------------------ right -------------------------- */

.price {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1;
  margin-bottom: clamp(24px, 5vh, 52px);
}

.price__now {
  font-size: clamp(30px, 2.9vw, 44px);
}

.price__was {
  margin-top: 8px;
  font-size: clamp(20px, 1.9vw, 30px);
  font-weight: 600;
  color: color-mix(in srgb, var(--ink) 78%, transparent);
  text-decoration: line-through;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.picker__label {
  display: block;
  margin-bottom: 13px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--ink);
}

.picker__row {
  display: flex;
  justify-content: flex-end;
  gap: 9px;
}

.chip {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1.4px solid color-mix(in srgb, var(--ink) 42%, transparent);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 240ms ease, border-color 240ms ease, color var(--dur-bg) var(--ease);
}

.chip small { font-size: 11px; font-weight: 500; }
.chip:hover { border-color: color-mix(in srgb, var(--ink) 85%, transparent); }

.chip.is-selected {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bg);
}

/* ---------------------------- bottom bar ----------------------- */

.botbar {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: end;
  gap: 20px;
  padding: var(--pad-y) var(--pad-x);
}

.social {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.social a {
  display: block;
  width: 17px;
  height: 17px;
  color: color-mix(in srgb, var(--ink) 90%, transparent);
  transition: color 200ms ease, transform 200ms ease;
}

.social a:hover { color: var(--ink); transform: translateY(-2px); }

.tagline {
  margin: 0;
  text-align: center;
  font-size: clamp(15px, 1.25vw, 18px);
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: .01em;
  color: var(--ink);
}

/* Peeks at the colourway you'd get if you clicked. */
.peek {
  justify-self: end;
  width: clamp(74px, 7vw, 104px);
  height: clamp(74px, 7vw, 104px);
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  transition: transform 300ms var(--ease);
}

.peek:hover { transform: scale(1.09) rotate(-3deg); }

.peek__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .3));
  transition: opacity 260ms ease;
}

.peek__img.is-swapping { opacity: 0; }

/* --------------------------- focus + a11y ---------------------- */

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
  }
}

/* ---------------------------- responsive ----------------------- */

/* The headline's min-content widens the left track past its 1fr share, so
   the centre track never lands on the viewport centre. Taking the product
   out of flow and centring it on the stage makes it exact regardless of
   how the text tracks resolve. */
@media (min-width: 721px) {
  .col--stage { position: static; }

  .machine {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    margin-inline: 0;
  }
}

@media (max-width: 1080px) {
  .nav { display: none; }
  .hero { grid-template-columns: 1fr 1.2fr; }
  .col--right {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-self: stretch;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    text-align: left;
  }
}

@media (max-width: 720px) {
  body, .stage { overflow: auto; }
  .stage { height: auto; min-height: 100%; }

  .hero {
    grid-template-columns: minmax(0, 1fr);
    text-align: center;
    padding-block: 4px 24px;
    gap: 26px;
  }

  /* Explicit rows for all three, so the 1080px placement rules above
     can't leak through and reorder the stack. */
  .col--stage { grid-column: 1; grid-row: 1; }
  .col--left  { grid-column: 1; grid-row: 2; max-width: none; justify-self: center; }
  .col--right {
    grid-column: 1;
    grid-row: 3;
    justify-self: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 26px;
    text-align: center;
  }

  .machine { width: min(84vw, 400px); max-height: none; }
  .pager { justify-content: center; margin-bottom: 20px; }
  .headline { font-size: clamp(34px, 11vw, 50px); }
  .blurb { margin-inline: auto; }
  .price { align-items: center; margin-bottom: 0; }
  .picker__row { justify-content: center; }

  .botbar { grid-template-columns: 1fr; justify-items: center; gap: 18px; }
  .peek { justify-self: center; }
}

/* =================================================================
   Subpages (build / about / contact)

   They reuse the themed chrome and backdrop, but scroll instead of
   locking to the viewport, and carry a fixed colourway rather than a
   carousel — set with a --bg/--ink/--paper triple on the <html> tag.
   ================================================================= */

body.page,
body.page .stage {
  height: auto;
  min-height: 100%;
  overflow: visible;
}

body.page { overflow-y: auto; }

/* The backdrop is sized to the viewport, not the document, so a long
   page doesn't stretch the halo into a smear. */
body.page .stage { background-attachment: fixed; }
body.page .stage::after { position: fixed; }

.page-main {
  position: relative;
  z-index: 2;
  padding: clamp(24px, 5vh, 64px) var(--pad-x) clamp(48px, 9vh, 110px);
}

.page-head {
  max-width: 760px;
  margin: 0 auto clamp(40px, 7vh, 84px);
  text-align: center;
}

.page-eyebrow {
  display: block;
  margin-bottom: 18px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink) 72%, transparent);
}

.page-title {
  margin: 0 0 20px;
  font-size: clamp(38px, 5vw, 68px);
  line-height: 1.02;
}

.page-lead {
  margin: 0 auto;
  max-width: 56ch;
  font-size: 18px;
  line-height: 1.65;
}

.wrap { max-width: 1080px; margin-inline: auto; }
.wrap--narrow { max-width: 720px; }

/* ------------------------------ build -------------------------- */

.build-shot {
  position: relative;
  width: min(52vw, 560px);
  aspect-ratio: 1322 / 1190;
  margin: 0 auto clamp(32px, 6vh, 72px);
}

.build-shot img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.build-shot__shadow {
  position: absolute;
  left: 50%;
  bottom: 0.5%;
  width: 52%;
  height: 4.5%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,.55), rgba(0,0,0,0) 70%);
  mix-blend-mode: multiply;
}

.specs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1px;
  margin: 0;
  background: color-mix(in srgb, var(--ink) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
  border-radius: 14px;
  overflow: hidden;
}

.specs > div {
  padding: 22px 24px;
  background: var(--bg);
}

.specs dt {
  margin-bottom: 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink);
}

.specs dd {
  margin: 0;
  font-size: 18px;
  font-weight: 500;
}

.section-title {
  margin: clamp(44px, 8vh, 90px) 0 20px;
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -.01em;
}

.prose p {
  margin: 0 0 18px;
  font-size: 18px;
  line-height: 1.7;
}

.prose p:last-child { margin-bottom: 0; }

.cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(24px, 4vw, 56px);
}

/* ----------------------------- contact ------------------------- */

.contact-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.contact-card {
  padding: 26px 26px 24px;
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  border-radius: 14px;
}

.contact-card h2 {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink);
}

.contact-card a,
.contact-card p {
  margin: 0;
  font-size: 18px;
  color: var(--ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.contact-card a:hover { text-decoration: underline; }

.contact-card .pending {
  font-size: 14px;
  color: var(--ink);
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: clamp(40px, 7vh, 80px);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .08em;
  color: var(--ink);
  text-decoration: none;
}

.back-link svg { width: 17px; height: 17px; stroke-width: 1.9; }
.back-link:hover { text-decoration: underline; }

@media (max-width: 720px) {
  .build-shot { width: min(86vw, 380px); }
}

/* Subpage footer carries only the tagline, so it centres rather than
   using the home page's three-column social / tagline / thumbnail row. */
.botbar--page {
  grid-template-columns: 1fr;
  justify-items: center;
  padding-bottom: clamp(28px, 5vh, 52px);
}

/* Inline links in body copy — otherwise they fall back to browser blue,
   which is unreadable on these backdrops. */
.prose a,
.page-lead a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--ink) 45%, transparent);
  transition: text-decoration-color 200ms ease;
}

.prose a:hover,
.page-lead a:hover { text-decoration-color: var(--ink); }
