/* Generated by build.mjs. Do not edit.
   Source of truth: src/css/ */
/* --- 01-tokens.css --- */
/* ---------------------------------------------------------------------------
   Tokens
   Design values lifted from the original Mo'Websites Tailwind theme so the
   demo reproduces the same identity without shipping Tailwind.
   Single source of truth: nothing below this file hard codes a colour, a
   shadow or a duration.
   --------------------------------------------------------------------------- */

:root {
  /* Palette. Monochrome by design. */
  --c-black: #000000;
  --c-white: #ffffff;
  --c-gray-50: #f9fafb;
  --c-gray-200: #e5e7eb;
  --c-gray-300: #d1d5db;
  --c-gray-400: #9ca3af;
  --c-gray-500: #6b7280;
  --c-gray-600: #4b5563;
  --c-gray-700: #374151;
  --c-gray-900: #111827;

  /* The one accent in the original design, kept for the contact panel. */
  --c-accent-300: #d8b4fe;

  /* Type families. Fallbacks are metric neighbours so a font failure is
     a shift in texture, not a shift in layout. */
  --f-display: "Orbitron", "Segoe UI", system-ui, sans-serif;
  --f-tech: "Rajdhani", "Segoe UI", system-ui, sans-serif;
  --f-serif: "Playfair Display", Georgia, "Times New Roman", serif;
  --f-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Type scale. Body sizes are floored at 16px, which the original was not. */
  --t-body: 1.0625rem; /* 17px, Rajdhani runs small for its em size */
  --t-body-sm: 1rem; /* 16px floor, never below */
  --t-label: 0.9375rem;
  --t-lede: 1.0625rem;
  --t-lede-md: 1.25rem;
  --t-h1: 1.875rem;
  --t-h1-sm: 3rem;
  --t-h1-xl: 3.75rem;
  --t-h2: 1.875rem;
  --t-h2-sm: 3rem;
  --t-h3: 1.25rem;
  --t-price: 2.25rem;

  --lh-tight: 1.1;
  --lh-heading: 1.15;
  --lh-body: 1.65;

  --track-wide: 0.05em;
  --track-widest: 0.1em;

  /* Spacing rhythm, matching the original py-12 / md:py-24 / lg:py-32. */
  --space-section: 3rem;
  --space-section-md: 6rem;
  --space-section-lg: 8rem;
  --gutter: 1rem;
  --gutter-md: 1.5rem;

  --header-h: 5rem;
  --tap-min: 2.75rem; /* 44px */

  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;

  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
  --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);

  --dur-fast: 200ms;
  --dur-med: 300ms;
  --dur-slow: 500ms;
  --dur-reveal: 700ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* Focus ring colour is re-declared by dark sections so it always contrasts. */
  --focus-ring: var(--c-black);
}

/* --- 02-base.css --- */
/* ---------------------------------------------------------------------------
   Base
   Reset, document defaults, typography, accessibility primitives and the
   global motion policy. Nothing component specific belongs here.
   --------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* clip rather than hidden: no scroll container is created, so position:
     sticky and fixed keep working while horizontal overflow is still cut. */
  overflow-x: clip;
}

body {
  margin: 0;
  overflow-x: clip;
  background-color: var(--c-white);
  color: var(--c-black);
  font-family: var(--f-tech);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
p,
ul,
figure {
  margin: 0;
}

ul {
  padding: 0;
  list-style: none;
}

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

img {
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
}

/* Long uppercase display type is the main overflow risk in this design.
   Break rather than push the viewport wide. */
h1,
h2,
h3 {
  overflow-wrap: break-word;
  text-wrap: balance;
}

/* Anchor targets must clear the fixed header. */
:target,
section[id] {
  scroll-margin-top: calc(var(--header-h) + 1rem);
}

/* --- Accessibility primitives --------------------------------------------- */

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

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

.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  transform: translateY(-120%);
  padding: 0.75rem 1.25rem;
  min-height: var(--tap-min);
  display: inline-flex;
  align-items: center;
  background-color: var(--c-black);
  color: var(--c-white);
  font-family: var(--f-tech);
  font-size: var(--t-body-sm);
  font-weight: 600;
  letter-spacing: var(--track-wide);
  transition: transform var(--dur-fast) var(--ease-out);
}

.skip-link:focus-visible {
  transform: translateY(0);
  outline-color: var(--c-white);
  outline-offset: -6px;
}

/* --- Scroll reveal --------------------------------------------------------
   Content is visible by default. The hidden starting state is applied only
   when scripting is available, so crawlers and no-script visitors always get
   the fully rendered page. */

/* Uses the standalone `translate` property, not `transform`, so components are
   free to own `transform` for their own hover states without a conflict. */
.js [data-reveal] {
  opacity: 0;
  translate: 0 2.5rem;
  transition: opacity var(--dur-reveal) var(--ease-out),
    translate var(--dur-reveal) var(--ease-out);
}

.js [data-reveal].is-revealed {
  opacity: 1;
  translate: none;
}

/* --- Motion policy --------------------------------------------------------
   One place decides how much this site is allowed to move. */

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }

  .js [data-reveal] {
    opacity: 1;
    translate: none;
  }
}

/* The original hid the scrollbar entirely, which removes a real affordance.
   Kept discreet and monochrome instead of removed. */
@supports selector(::-webkit-scrollbar) {
  ::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  ::-webkit-scrollbar-track {
    background: var(--c-gray-50);
  }
  ::-webkit-scrollbar-thumb {
    background: var(--c-gray-300);
    border-radius: 999px;
  }
  ::-webkit-scrollbar-thumb:hover {
    background: var(--c-gray-400);
  }
}

html {
  scrollbar-width: thin;
  scrollbar-color: var(--c-gray-300) var(--c-gray-50);
}

@media print {
  .site-header,
  .hero__scroll,
  .cursor {
    display: none !important;
  }
}

/* --- 03-layout.css --- */
/* ---------------------------------------------------------------------------
   Layout
   Container, section rhythm and the shared section heading block. These are
   the three patterns every section reuses, so they live in one place rather
   than being restated per component.
   --------------------------------------------------------------------------- */

.container {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

@media (min-width: 640px) {
  .container {
    max-width: 640px;
  }
}
@media (min-width: 768px) {
  .container {
    max-width: 768px;
    padding-inline: var(--gutter-md);
  }
}
@media (min-width: 1024px) {
  .container {
    max-width: 1024px;
  }
}
@media (min-width: 1280px) {
  .container {
    max-width: 1280px;
  }
}
@media (min-width: 1400px) {
  .container {
    max-width: 1400px;
  }
}

/* Body content starts below the fixed header. */
main {
  padding-top: var(--header-h);
}

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

.section {
  position: relative; /* decorative rules are absolutely placed inside */
  width: 100%;
  padding-block: var(--space-section);
  overflow: hidden;
}

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

.section--dark {
  background-color: var(--c-black);
  color: var(--c-white);
  --focus-ring: var(--c-white);
}

.section--muted {
  background-color: var(--c-gray-50);
}

.section--rise {
  background-image: linear-gradient(to bottom, var(--c-white), var(--c-gray-50));
}

.section--fall {
  background-image: linear-gradient(to bottom, var(--c-gray-50), var(--c-white));
}

.section__rule {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 1px;
  background-image: linear-gradient(
    to right,
    transparent,
    rgb(255 255 255 / 0.3),
    transparent
  );
}

/* --- Shared heading block -------------------------------------------------- */

.section__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  text-align: center;
  margin-bottom: 3rem;
}

.section__head--tight {
  gap: 1rem;
}

.badge {
  display: inline-block;
  border-radius: var(--radius-lg);
  padding: 0.25rem 0.75rem;
  font-family: var(--f-tech);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--track-wide);
  line-height: 1.5;
}

.badge--dark {
  background-color: var(--c-black);
  color: var(--c-white);
}

.badge--light {
  background-color: var(--c-white);
  color: var(--c-black);
}

.section__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: var(--t-h2);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

@media (min-width: 640px) {
  .section__title {
    font-size: var(--t-h2-sm);
  }
}

.section__title--sm {
  font-size: var(--t-h2);
}

@media (min-width: 640px) {
  .section__title--sm {
    font-size: 2.25rem;
  }
}

.section__lede {
  max-width: 56ch;
  color: var(--c-gray-500);
  font-size: var(--t-lede);
  line-height: var(--lh-body);
}

@media (min-width: 768px) {
  .section__lede {
    font-size: var(--t-lede-md);
  }
}

.section--dark .section__lede,
.section__lede--dark {
  color: var(--c-gray-400);
}

/* --- 04-buttons.css --- */
/* ---------------------------------------------------------------------------
   Buttons
   One button component with modifiers, replacing the six near-identical
   inline variants the original repeated across sections. Every variant meets
   the 44px minimum target height.
   --------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--tap-min);
  padding-inline: 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-family: var(--f-tech);
  font-size: var(--t-body-sm);
  font-weight: 600;
  letter-spacing: var(--track-wide);
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  transition: background-color var(--dur-med) var(--ease-out),
    color var(--dur-med) var(--ease-out), border-color var(--dur-med) var(--ease-out),
    box-shadow var(--dur-med) var(--ease-out);
}

.btn--lg {
  min-height: 3rem;
  padding-inline: 2rem;
}

.btn--block {
  width: 100%;
}

.btn__arrow,
.btn__lead {
  flex: none;
  width: 1rem;
  height: 1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--dur-med) var(--ease-out), opacity var(--dur-med) var(--ease-out);
}

.btn:hover .btn__arrow,
.btn:focus-visible .btn__arrow {
  transform: translateX(0.25rem);
}

/* Reveal-on-hover arrow used by the contact button. Always present for
   keyboard users, never a layout shift. */
.btn__arrow--hover {
  opacity: 0;
  transform: translateX(-0.5rem);
}

.btn:hover .btn__arrow--hover,
.btn:focus-visible .btn__arrow--hover {
  opacity: 1;
  transform: translateX(0);
}

/* --- Variants -------------------------------------------------------------- */

/* Light fill, for use on black. */
.btn--solid-light {
  background-color: var(--c-white);
  color: var(--c-black);
  border-color: var(--c-white);
  box-shadow: var(--shadow-sm);
}

.btn--solid-light:hover {
  background-color: transparent;
  color: var(--c-white);
}

/* Outline, for use on black. */
.btn--outline-light {
  background-color: transparent;
  color: var(--c-white);
  border-color: var(--c-white);
  box-shadow: var(--shadow-sm);
}

.btn--outline-light:hover {
  background-color: var(--c-white);
  color: var(--c-black);
}

/* Dark fill, for use on white. */
.btn--solid-dark {
  background-color: var(--c-black);
  color: var(--c-white);
  border-color: var(--c-black);
  box-shadow: var(--shadow-sm);
}

.btn--solid-dark:hover {
  background-color: var(--c-white);
  color: var(--c-black);
  box-shadow: var(--shadow-lg), 0 0 0 1px var(--c-black);
}

/* --- 05-header.css --- */
/* ---------------------------------------------------------------------------
   Header and navigation
   One navigation list serves both breakpoints. The original shipped two
   duplicate copies of the same links; this styles a single source as a row on
   desktop and a full screen overlay on mobile.
   --------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  height: var(--header-h);
  background-color: var(--c-white);
  border-bottom: 1px solid rgb(0 0 0 / 0.1);
  transition: box-shadow var(--dur-med) var(--ease-out),
    background-color var(--dur-med) var(--ease-out);
}

.site-header.is-scrolled {
  background-color: rgb(255 255 255 / 0.95);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow-md);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: 100%;
  padding-inline: var(--gutter);
}

@media (min-width: 1024px) {
  .site-header__inner {
    padding-inline: var(--gutter-md);
  }
}

/* --- Brand ----------------------------------------------------------------- */

.brand {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

/* Logo lockup: geometric mark plus wordmark. The wordmark stays live text so
   it is selectable, searchable and never a blurry image. Inline-flex with a
   minimum height so the whole lockup is a full size target rather than a 29px
   strip of text. */
.brand__mark {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--tap-min);
  transition: opacity var(--dur-fast) var(--ease-out);
}

.brand__mark:hover {
  opacity: 0.8;
}

.brand__glyph {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 7;
  stroke-linecap: butt;
  stroke-linejoin: miter;
}

.brand__word {
  font-family: var(--f-serif);
  font-weight: 700;
  font-size: 1.5rem;
  line-height: 1.2;
}

.brand__mark--sm .brand__glyph {
  width: 1.25rem;
  height: 1.25rem;
}

.brand__mark--sm .brand__word {
  font-size: 1.25rem;
}

/* Always visible honesty marker. Uses the pill language already in the
   design so it reads as part of the identity, not as a warning banner. */
.brand__flag {
  flex: none;
  border: 1px solid var(--c-black);
  border-radius: var(--radius-md);
  padding: 0.1875rem 0.5rem;
  font-family: var(--f-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: var(--track-widest);
  line-height: 1.4;
  text-transform: uppercase;
  white-space: nowrap;
}

/* --- Toggle ---------------------------------------------------------------- */

.nav-toggle {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: var(--tap-min);
  height: var(--tap-min);
  border-radius: 999px;
  background-color: var(--c-black);
  color: var(--c-white);
  cursor: pointer;
  transition: transform var(--dur-med) var(--ease-out);
}

.nav-toggle:hover {
  transform: scale(1.05);
}

.nav-toggle:focus-visible {
  outline-color: var(--c-black);
  outline-offset: 3px;
}

.nav-toggle svg {
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.nav-toggle__label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.nav-toggle__close,
.nav-toggle[aria-expanded="true"] .nav-toggle__open {
  display: none;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__close {
  display: block;
}

@media (min-width: 768px) {
  .nav-toggle {
    display: none;
  }
}

/* Scroll lock while the overlay is open, applied on the root element so the
   original's habit of writing body.style.overflow back to "auto" cannot
   clobber a value the page did not set.

   `overflow: hidden` on its own is advisory on iOS Safari, which keeps
   scrolling the page behind the panel. Taking the body out of flow is the part
   that actually holds. It costs the scroll position, so 02-nav.js pins the
   body at a negative offset matching the current scroll and puts it back on
   close; without that the page would snap to the top every time the menu was
   opened halfway down. */
html.is-nav-open,
html.is-nav-open body {
  overflow: hidden;
}

html.is-nav-open body {
  position: fixed;
  inset-inline: 0;
  width: 100%;
}

/* --- Navigation, mobile overlay -------------------------------------------- */

@media (max-width: 767.98px) {
  /* The overlay below is `position: fixed` and it lives inside this header. A
     `backdrop-filter` on an ancestor promotes that ancestor to the containing
     block for its fixed descendants, so the moment `.is-scrolled` applied the
     panel stopped resolving `inset: 0` against the viewport and collapsed into
     the 5rem header strip: menu items landed on top of the page content and
     the links could not be tapped. Opening the menu anywhere except the very
     top of the page hit this. The frosted bar is a desktop refinement for that
     reason; on mobile the scrolled bar is simply opaque, which at 0.95 alpha
     it very nearly was already. Nothing here may reintroduce a containing
     block: no transform, no filter, no will-change on .site-header. */
  .site-header.is-scrolled {
    background-color: var(--c-white);
    backdrop-filter: none;
  }

  .nav {
    position: fixed;
    inset: 0;
    z-index: 1;
    display: flex;
    /* Clears the header bar, which stays legible above the panel. */
    padding: calc(var(--header-h) + 1rem) 1.5rem 2rem;
    overflow-y: auto;
    /* A flick that runs past the end of the menu must not scroll the page
       underneath it. */
    overscroll-behavior: contain;
    /* Opaque rather than the old 0.97: three per cent was enough for the white
       buttons behind the panel to read as bright bands across the menu. With
       no transparency left to sample there is nothing for a backdrop blur to
       do, so that goes too, and with it a compositing layer on exactly the
       devices least able to afford one. */
    background-image: linear-gradient(
      to bottom right,
      var(--c-black),
      var(--c-gray-900)
    );
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-slow) var(--ease-out),
      visibility var(--dur-slow) var(--ease-out);
  }

  .nav.is-open {
    opacity: 1;
    visibility: visible;
  }

  .nav__list {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.5rem;
    width: 100%;
    max-width: 22rem;
    /* Centres the menu, but degrades safely. `align-items: center` on the
       panel would push the first items above its top edge once the list is
       taller than the viewport — large text, or a phone held sideways — and
       overflow above the scroll origin cannot be scrolled back to. Auto
       margins resolve to zero instead of going negative. */
    margin: auto;
  }

  /* The bar stays readable over the panel, so opening the menu reads as the
     header expanding rather than the studio name disappearing. */
  .brand {
    position: relative;
    z-index: 2;
    transition: color var(--dur-med) var(--ease-out);
  }

  html.is-nav-open .brand {
    color: var(--c-white);
  }

  html.is-nav-open .brand__flag {
    border-color: var(--c-white);
  }

  .nav__item {
    opacity: 0;
    transform: translateY(1rem);
    transition: opacity var(--dur-reveal) var(--ease-out),
      transform var(--dur-reveal) var(--ease-out);
    transition-delay: var(--stagger, 0ms);
  }

  .nav.is-open .nav__item {
    opacity: 1;
    transform: none;
  }

  .nav__link,
  .nav__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--tap-min);
    padding-inline: 0.5rem;
    font-family: var(--f-display);
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: var(--track-wide);
    text-transform: uppercase;
    color: var(--c-white);
    transition: color var(--dur-med) var(--ease-out);
  }

  .nav__link:hover {
    color: var(--c-gray-300);
  }

  /* The contact item is a plain link inside the overlay; the dedicated
     email button below it carries the emphasis. */
  .nav__cta {
    background: none;
    border: 0;
    box-shadow: none;
    color: var(--c-white);
  }

  .nav__cta:hover {
    background: none;
    color: var(--c-gray-300);
  }

  .nav__item--overlay-only {
    margin-top: 0.5rem;
  }

  .nav :focus-visible {
    outline-color: var(--c-white);
  }
}

/* --- Navigation, mobile without scripting ----------------------------------
   The overlay can only be opened by script, so without it the toggle would be
   a dead control and the menu unreachable. Fall back to a plain wrapped row
   and drop the toggle. Browsers without the `scripting` media feature simply
   keep the behaviour above, which is the current baseline. */

@media (max-width: 767.98px) and (scripting: none) {
  .site-header {
    position: static;
    height: auto;
  }

  main {
    padding-top: 0;
  }

  .site-header__inner {
    flex-wrap: wrap;
    height: auto;
    padding-block: 0.75rem;
  }

  .nav-toggle {
    display: none;
  }

  .nav {
    position: static;
    width: 100%;
    padding: 0;
    overflow: visible;
    background: none;
    backdrop-filter: none;
    opacity: 1;
    visibility: visible;
  }

  .nav__list {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 0 1rem;
    max-width: none;
    margin: 0;
  }

  .nav__item {
    opacity: 1;
    transform: none;
  }

  .nav__link,
  .nav__cta {
    padding-inline: 0;
    font-family: var(--f-tech);
    font-size: var(--t-body-sm);
    letter-spacing: 0.01em;
    text-transform: none;
    color: var(--c-black);
  }

  .nav__link:hover,
  .nav__cta:hover {
    color: var(--c-gray-500);
  }

  .nav__item--overlay-only {
    display: none;
  }
}

/* --- Navigation, desktop row ----------------------------------------------- */

@media (min-width: 768px) {
  .nav__list {
    display: flex;
    align-items: center;
    gap: 1.5rem;
  }

  .nav__link {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap-min);
    font-family: var(--f-tech);
    font-size: var(--t-body-sm);
    font-weight: 600;
    letter-spacing: 0.01em;
    transition: color var(--dur-med) var(--ease-out);
  }

  .nav__link:hover {
    color: var(--c-gray-500);
  }

  .nav__item--overlay-only {
    display: none;
  }
}

/* --- 06-hero.css --- */
/* ---------------------------------------------------------------------------
   Hero
   Entrance motion is pure CSS with fill-mode both, so the hero never depends
   on scripting to become readable and the reduced motion policy in the base
   layer collapses it to an instant paint.
   --------------------------------------------------------------------------- */

.hero {
  position: relative;
  width: 100%;
  padding-block: var(--space-section);
  background-color: var(--c-black);
  color: var(--c-white);
  overflow: hidden;
  --focus-ring: var(--c-white);
}

@media (min-width: 768px) {
  .hero {
    padding-block: var(--space-section-md);
  }
}
@media (min-width: 1024px) {
  .hero {
    padding-block: var(--space-section-lg);
  }
}
@media (min-width: 1280px) {
  .hero {
    padding-block: 10rem;
  }
}

.hero__grid {
  display: grid;
  gap: 1.5rem;
}

@media (min-width: 1024px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1fr) 400px;
    gap: 3rem;
    align-items: center;
  }
}

@media (min-width: 1280px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1fr) 600px;
  }
}

.hero__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1rem;
  min-width: 0;
}

.hero__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: var(--t-h1);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  animation: slide-up 0.8s var(--ease-out) both;
}

@media (min-width: 640px) {
  .hero__title {
    font-size: var(--t-h1-sm);
  }
}

@media (min-width: 1280px) {
  .hero__title {
    font-size: var(--t-h1-xl);
    line-height: var(--lh-tight);
  }
}

/* Second line wipes in, as in the original. Block level so the line break is
   structural rather than a hidden <br>. */
.hero__title-reveal {
  display: block;
  animation: reveal-text 1.2s cubic-bezier(0.77, 0, 0.175, 1) 0.5s both;
}

.hero__lede {
  max-width: 40rem;
  color: var(--c-gray-300);
  font-size: var(--t-lede);
  line-height: var(--lh-body);
  animation: slide-up 0.8s var(--ease-out) 0.7s both;
}

@media (min-width: 768px) {
  .hero__lede {
    font-size: var(--t-lede-md);
  }
}

.hero__actions {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  animation: slide-up 0.8s var(--ease-out) 0.9s both;
}

@media (min-width: 400px) {
  .hero__actions {
    flex-direction: row;
    flex-wrap: wrap;
  }
}

/* --- Media ----------------------------------------------------------------- */

.hero__media {
  display: none;
}

@media (min-width: 1024px) {
  .hero__media {
    display: block;
    min-width: 0;
  }
}

.hero__frame {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-xl);
  overflow: hidden;
}

.hero__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: linear-gradient(
    to bottom right,
    var(--c-black),
    transparent,
    var(--c-black)
  );
  opacity: 0.6;
  pointer-events: none;
}

.hero__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  animation: float 6s ease-in-out infinite;
  /* `scale` rather than a transform, so the hover zoom composes with the
     float animation instead of being overwritten by it. */
  transition: scale var(--dur-reveal) var(--ease-out);
}

.hero__frame:hover .hero__image {
  scale: 1.08;
}

.hero__frame-rule {
  position: absolute;
  inset: 0;
  z-index: 2;
  border: 1px solid rgb(255 255 255 / 0.3);
  transform: scale(0.95);
  transition: transform var(--dur-reveal) var(--ease-out);
  pointer-events: none;
}

.hero__frame:hover .hero__frame-rule {
  transform: scale(1);
}

/* --- Scroll cue ------------------------------------------------------------ */

.hero__scroll {
  display: none;
}

@media (min-width: 768px) {
  .hero__scroll {
    display: block;
    position: absolute;
    bottom: 1.25rem;
    left: 50%;
    transform: translateX(-50%);
  }
}

.hero__scroll-mouse {
  display: flex;
  justify-content: center;
  width: 1.5rem;
  height: 2.5rem;
  border: 2px solid var(--c-white);
  border-radius: 999px;
}

.hero__scroll-wheel {
  width: 0.25rem;
  height: 0.5rem;
  margin-top: 0.5rem;
  border-radius: 999px;
  background-color: var(--c-white);
  animation: pulse-subtle 4s ease-in-out infinite;
}

/* --- Keyframes ------------------------------------------------------------- */

@keyframes slide-up {
  from {
    opacity: 0;
    transform: translateY(1.25rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes reveal-text {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}

@keyframes float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

@keyframes pulse-subtle {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.8;
  }
}

/* --- 07-checklist.css --- */
/* ---------------------------------------------------------------------------
   Checklist
   The practice principles list on the dark section.
   --------------------------------------------------------------------------- */

.checklist {
  display: grid;
  gap: 1.5rem;
  max-width: 64rem;
  margin-inline: auto;
}

@media (min-width: 1024px) {
  .checklist {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2.5rem;
  }
}

.checklist__item {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  min-width: 0;
}

.checklist__mark {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-top: 0.125rem;
  border-radius: 999px;
  background-color: var(--c-white);
  color: var(--c-black);
  transition: transform var(--dur-med) var(--ease-out);
}

.checklist__item:hover .checklist__mark {
  transform: scale(1.1);
}

.checklist__mark svg {
  width: 1rem;
  height: 1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.checklist__text {
  min-width: 0;
  font-family: var(--f-tech);
  font-size: 1.1875rem;
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: 0.01em;
  /* Underline grows from the left on hover, as in the original. */
  background-image: linear-gradient(var(--c-white), var(--c-white));
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0 1px;
  transition: background-size var(--dur-slow) var(--ease-out);
}

.checklist__item:hover .checklist__text {
  background-size: 100% 1px;
}

/* --- 08-pillars.css --- */
/* ---------------------------------------------------------------------------
   Pillars
   Three-up icon cards used by the approach section.
   --------------------------------------------------------------------------- */

.pillar-grid {
  display: grid;
  gap: 1.5rem;
  max-width: 64rem;
  margin-inline: auto;
}

@media (min-width: 640px) {
  .pillar-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .pillar-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2.5rem;
  }
}

.pillar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  min-width: 0;
  padding: 1.5rem;
  border: 1px solid var(--c-gray-200);
  border-radius: var(--radius-lg);
  background-color: var(--c-white);
  box-shadow: var(--shadow-sm);
  text-align: center;
  transition: box-shadow var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
}

.pillar:hover {
  box-shadow: var(--shadow-lg);
  transform: translateY(-0.25rem);
}

.pillar__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.75rem;
  border: 1px solid var(--c-gray-200);
  border-radius: 999px;
  background-color: var(--c-black);
  color: var(--c-white);
}

.pillar__icon svg {
  width: 1.5rem;
  height: 1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.pillar__title {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-h3);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

.pillar__body {
  color: var(--c-gray-600);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
}

/* --- 09-tiers.css --- */
/* ---------------------------------------------------------------------------
   Tiers
  The three engagement cards. The featured card carries a corner ribbon,
  which the original allowed to collide with the card title on narrow screens.
   --------------------------------------------------------------------------- */

.tier-grid {
  display: grid;
  gap: 1.5rem;
  max-width: 64rem;
  margin-inline: auto;
}

@media (min-width: 768px) {
  .tier-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .tier-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2rem;
  }
}

.tier {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  border: 2px solid var(--c-gray-200);
  border-radius: var(--radius-lg);
  background-color: rgb(255 255 255 / 0.9);
  transition: transform var(--dur-slow) var(--ease-out),
    box-shadow var(--dur-slow) var(--ease-out);
}

.tier:hover {
  transform: translateY(-0.25rem);
}

.tier--featured {
  border-color: var(--c-black);
  box-shadow: var(--shadow-xl);
}

.tier--featured:hover {
  transform: translateY(-0.5rem);
}

/* The badge reads as a corner ribbon but is a normal flow item, bled out to
   the card's top right corner with negative margins. Absolutely positioned it
   needed the card head to reserve a fixed 3rem of clearance for it, and that
   reserve was a guess: at 320px the label wraps to two lines, which is 50px,
   and the title moved underneath it. In flow the head cannot help but make
   room, at any width, any label and any text size. */
.tier__ribbon {
  align-self: flex-end;
  /* Cancels the head's padding on two sides so the badge meets the corner. */
  margin: -1.5rem -1.5rem 0.25rem 0;
  max-width: calc(100% + 1.5rem);
  padding: 0.25rem 1rem;
  border-bottom-left-radius: var(--radius-lg);
  background-image: linear-gradient(
    to right,
    var(--c-black),
    var(--c-gray-700),
    var(--c-black)
  );
  color: var(--c-white);
  font-family: var(--f-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: var(--track-wide);
  line-height: 1.6;
  text-transform: uppercase;
  text-align: right;
  box-shadow: var(--shadow-lg);
}

@media (min-width: 480px) {
  .tier__ribbon {
    font-size: 0.875rem;
  }
}

.tier__head {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.5rem;
  background-image: linear-gradient(to bottom, transparent, rgb(249 250 251 / 0.3));
}

.tier__name {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 1.5rem;
  line-height: var(--lh-heading);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

.tier__desc {
  color: var(--c-gray-600);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
}

.tier__price {
  font-family: var(--f-tech);
  font-size: var(--t-price);
  font-weight: 700;
  line-height: 1.2;
}

.tier__body {
  padding: 0 1.5rem 1.5rem;
}

.tier__features {
  display: grid;
  gap: 0.625rem;
}

.tier__features li {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  color: var(--c-gray-700);
  font-size: var(--t-body-sm);
  line-height: 1.5;
}

.tier__tick {
  flex: none;
  margin-top: 0.1875rem;
}

.tier__tick svg {
  width: 1rem;
  height: 1rem;
  fill: none;
  stroke: var(--c-black);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.tier__foot {
  margin-top: auto;
  padding: 0 1.5rem 1.5rem;
  background-image: linear-gradient(to top, rgb(249 250 251 / 0.3), transparent);
}

.tier-note {
  max-width: 64rem;
  margin: 1.5rem auto 0;
  color: var(--c-gray-500);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
  text-align: center;
}

/* --- 10-projects.css --- */
/* ---------------------------------------------------------------------------
   Projects
   Selected work cards. The desaturate-to-colour reveal from the original is
   preserved: artwork is authored in muted colour and shown grey until hover.
   --------------------------------------------------------------------------- */

.project-grid {
  display: grid;
  gap: 1.5rem;
  max-width: 64rem;
  margin-inline: auto;
}

@media (min-width: 768px) {
  .project-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .project-grid {
    gap: 3rem;
  }
}

.project {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--c-gray-200);
  border-radius: var(--radius-lg);
  background-color: var(--c-white);
  transition: box-shadow var(--dur-slow) var(--ease-out);
}

.project:hover {
  box-shadow: var(--shadow-2xl);
}

.project__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

/* Scrim on hover. Scoped to the media box, which is the positioned ancestor,
   so it can no longer escape the card as it did in the original. */
.project__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    to bottom,
    transparent,
    transparent,
    rgb(0 0 0 / 0.7)
  );
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
  pointer-events: none;
}

.project:hover .project__media::after {
  opacity: 1;
}

.project__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}

.project:hover .project__image {
  filter: grayscale(0);
  transform: scale(1.08);
}

.project__body {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  padding: 1.25rem;
}

.project__title {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--t-h3);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

.project__category {
  color: var(--c-gray-500);
  font-size: var(--t-body-sm);
  font-weight: 600;
  letter-spacing: var(--track-wide);
}

.project__desc {
  color: var(--c-gray-600);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
}

/* --- 11-notes.css --- */
/* ---------------------------------------------------------------------------
   Notes
   Journal cards.
   --------------------------------------------------------------------------- */

.note-grid {
  display: grid;
  gap: 1.5rem;
}

@media (min-width: 640px) {
  .note-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

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

.note {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
  padding: 1.5rem;
  border: 1px solid var(--c-gray-200);
  border-radius: var(--radius-lg);
  background-color: var(--c-white);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-reveal) var(--ease-out);
}

.note:hover {
  box-shadow: var(--shadow-xl);
}

.note__title {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 1.125rem;
  line-height: 1.3;
  letter-spacing: 0.02em;
}

.note__desc {
  color: var(--c-gray-600);
  font-size: var(--t-body-sm);
  font-weight: 600;
  line-height: var(--lh-body);
}

.note__body {
  margin-top: 0.25rem;
  color: var(--c-gray-700);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
}

/* --- 12-contact.css --- */
/* ---------------------------------------------------------------------------
   Contact
   Enquiry block and the animated marquee panel, the single point of colour in
   the whole design.
   --------------------------------------------------------------------------- */

.contact__grid {
  display: grid;
  gap: 1.5rem;
}

@media (min-width: 1024px) {
  .contact__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 3rem;
    align-items: stretch;
  }
}

.contact__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.75rem;
  min-width: 0;
}

.contact__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.5rem;
  max-width: 100%;
}

/* The email address is long; let the button wrap rather than push the page. */
.contact__actions .btn {
  max-width: 100%;
  overflow-wrap: anywhere;
}

.contact__meta {
  color: var(--c-gray-400);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
}

.contact__panel {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}

.marquee {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 12rem;
  height: 100%;
  padding: 2rem;
  border-radius: var(--radius-xl);
  background-image: linear-gradient(to right, var(--c-black), var(--c-gray-900));
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.08);
  text-align: center;
}

.marquee__text {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 1.5rem;
  line-height: 1.25;
  letter-spacing: var(--track-wide);
  background-image: linear-gradient(
    to right,
    var(--c-white),
    var(--c-accent-300),
    var(--c-white)
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (min-width: 768px) {
  .marquee__text {
    font-size: 2.25rem;
  }
}

@media (min-width: 1024px) {
  .marquee__text {
    font-size: 2.75rem;
  }
}

.marquee__caret {
  animation: caret-blink 1s steps(2, start) infinite;
}

@keyframes caret-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

/* --- 13-footer.css --- */
/* ---------------------------------------------------------------------------
   Footer
   Carries the second, permanent statement that this is a concept.
   --------------------------------------------------------------------------- */

.site-footer {
  width: 100%;
  padding-block: 2rem;
  background-color: var(--c-white);
  border-top: 1px solid var(--c-gray-200);
}

.site-footer__top {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

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

.site-footer__brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
}

@media (min-width: 768px) {
  .site-footer__brand {
    align-items: flex-start;
  }
}

.site-footer__tagline {
  color: var(--c-gray-600);
  font-size: var(--t-body-sm);
  line-height: 1.5;
  text-align: center;
}

@media (min-width: 768px) {
  .site-footer__tagline {
    text-align: left;
  }
}

/* Placeholder marks, not links. A concept has no social accounts, and a link
   to nowhere is a defect rather than a detail. */
.site-footer__social {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.site-footer__icon svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: var(--c-gray-400);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.site-footer__bottom {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--c-gray-200);
  text-align: center;
}

.site-footer__disclaimer {
  max-width: 60ch;
  color: var(--c-gray-600);
  font-size: 0.9375rem;
  line-height: 1.6;
}

.site-footer__copyright {
  color: var(--c-gray-500);
  font-size: 0.9375rem;
}

/* --- 14-cursor.css --- */
/* ---------------------------------------------------------------------------
   Cursor
   The original applied `cursor: none !important` to every element
   unconditionally, which removed the pointer on touch devices, on keyboard
   only sessions and whenever the script failed. Here the native cursor is only
   hidden once the replacement is proven to be running, and only on devices
   with a fine pointer.
   --------------------------------------------------------------------------- */

.cursor {
  display: none;
}

@media (pointer: fine) {
  html.has-cursor,
  html.has-cursor body {
    cursor: none;
  }

  html.has-cursor a,
  html.has-cursor button {
    cursor: none;
  }

  .has-cursor .cursor {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 60;
    display: block;
    pointer-events: none;
    mix-blend-mode: difference;
    translate: calc(var(--cursor-x, -100px) - 50%) calc(var(--cursor-y, -100px) - 50%);
  }

  .cursor__ring {
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid var(--c-white);
    border-radius: 999px;
    opacity: 0.8;
    transition: width var(--dur-fast) var(--ease-out),
      height var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
  }

  .cursor.is-over-target .cursor__ring {
    width: 2.5rem;
    height: 2.5rem;
  }

  .cursor.is-pressed .cursor__ring {
    opacity: 0.5;
  }

  .cursor__dot {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 4px;
    height: 4px;
    margin: -2px 0 0 -2px;
    border-radius: 999px;
    background-color: var(--c-white);
  }
}

/* A pointer replacement that lags the real one is a usability cost with no
   benefit, so it is not offered to visitors who have asked for less motion. */
@media (prefers-reduced-motion: reduce) {
  html.has-cursor,
  html.has-cursor body,
  html.has-cursor a,
  html.has-cursor button {
    cursor: auto;
  }

  .cursor {
    display: none !important;
  }
}

/* --- 15-notfound.css --- */
/* ---------------------------------------------------------------------------
   Not found
   Its own page, so it gets its own small module rather than being bolted on
   to the home page styles.
   --------------------------------------------------------------------------- */

.notfound {
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: var(--space-section);
  background-color: var(--c-black);
  color: var(--c-white);
  --focus-ring: var(--c-white);
}

.notfound__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  max-width: 46rem;
}

.notfound__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: var(--t-h2);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
}

@media (min-width: 640px) {
  .notfound__title {
    font-size: var(--t-h2-sm);
  }
}

.notfound__lede {
  color: var(--c-gray-300);
  font-size: var(--t-lede);
  line-height: var(--lh-body);
}

.notfound__note {
  margin-top: 1rem;
  color: var(--c-gray-400);
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
}
