/* ---------------------------------------------------------------------------
   Andrew Le Maistre Landscapes — foundations

   Sources: Illustrator artboards (Client Docs/*.ai) are authoritative.
   Desktop artboards are 1440 wide, mobile 720 — exactly half — so the fluid
   scale below interpolates between two real designs rather than guessing.
   --------------------------------------------------------------------------- */

/* --- Open Sans, self-hosted -------------------------------------------------
   Google serves Open Sans as a VARIABLE font (wght 300-800); requesting four
   weights returns four rules pointing at one file. Deduplicated: 312KB -> 104KB.
   The italic is a static single weight, which is all the design uses.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Open Sans";
  src: url("../assets/fonts/open-sans-latin.woff2") format("woff2");
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Open Sans";
  src: url("../assets/fonts/open-sans-latin-ext.woff2") format("woff2");
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Open Sans";
  src: url("../assets/fonts/open-sans-italic-latin.woff2") format("woff2");
  font-weight: 600;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Open Sans";
  src: url("../assets/fonts/open-sans-italic-latin-ext.woff2") format("woff2");
  font-weight: 600;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Fraunces (display) -----------------------------------------------------
   Designer's replacement for PP Woodland. SIL OFL, so it is free for web use —
   this removes the licence purchase that was blocking every heading (ISS-001).

   PINNED, not variable. Fraunces ships four axes (opsz 9-144, wght 100-900,
   SOFT 0-100, WONK 0-1) and the full latin variable file is 118KB. The design
   uses a single weight, so pinning to opsz 144 / wght 400 gives 17KB — an 86%
   saving. Tuning SOFT/WONK later means swapping this file, not a code change.

   Watch out if anyone re-adds the variable version: Fraunces defaults to
   wght 900, WONK 1 and opsz 9, so without explicit font-variation-settings
   headings render black, wonky and optically sized for 9px text.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Fraunces";
  src: url("../assets/fonts/fraunces-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Fraunces";
  src: url("../assets/fonts/fraunces-latin-ext.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Metric-matched stand-in for the brief moment before Fraunces loads, built
   from the already-loaded Open Sans so it costs no extra download. Measured:
     Fraunces   upm 2000  x-height 964 (0.4820)  asc 1956  desc -510
     Open Sans  upm 2048  x-height 1096 (0.5352) asc 2189  desc -600 */
@font-face {
  font-family: "Fraunces Fallback";
  src: local("Open Sans"), url("../assets/fonts/open-sans-latin.woff2") format("woff2");
  size-adjust: 90.06%;
  ascent-override: 108.59%;
  descent-override: 28.31%;
  line-gap-override: 0%;
  font-display: swap;
}

:root {
  /* Brand palette — sampled from the exported vector fills */
  --magenta: #ea068c;
  --magenta-soft: #e665a2;
  --pink-pale: #f5c1da;
  --plum: #57253b;
  --white: #fff;
  --black: #000;

  --font-display: "Fraunces", "Fraunces Fallback", Georgia, serif;
  --font-body: "Open Sans", system-ui, -apple-system, sans-serif;

  /* --- Fluid type ----------------------------------------------------------
     Each max is the desktop comp's value; each vw figure is that value as a
     proportion of the 1440 artboard, so at exactly 1440 the page renders at
     comp size. Mins are floors for small screens, not comp values — the mobile
     artboards use a different layout, handled in T-015.

     rem-based mins mean browser zoom and OS text-size settings still work,
     which the previous transform: scale() approach silently defeated.
     ------------------------------------------------------------------------ */
  --fs-display: clamp(2rem, 3.854vw, 55.5px);   /*  55.5 / 1440 */
  --fs-heading: clamp(1.75rem, 2.569vw, 37px);  /*  37   / 1440 */
  --fs-tile: clamp(1.125rem, 2.014cqw, 29px);   /*  29 / 1440 — was 25.9 (client 2026-10-21: more legible) */
  --fs-lead: clamp(1.125rem, 1.667vw, 24px);    /*  24   / 1440 */
  --fs-body: clamp(0.9375rem, 1.111vw, 16px);   /*  16   / 1440 */
  --fs-ui: clamp(0.75rem, 0.833vw, 12px);       /*  12   / 1440 */

  /* The design artboard. The site canvas caps here — see .site below. */
  --design-w: 1440;

  /* Content column: the comp runs 192.5 -> 1247.5, i.e. 1055 wide, centred.
     The INNER pages use a wider column — see .site-inner below. */
  --wrap: 1055px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  /* Layout switch. The mobile artboard is 720 and the desktop 1440; 900 sits
     in the gap, below which the desktop grid stops being usable. */
  --bp-mobile: 900px;

  /* Negative inset that cancels the white margin either side of the capped
     .site canvas — see .bleed below. Named rather than repeated so the one
     expression that defines "escape the canvas" lives in a single place. */
  --bleed-inset: calc(50% - 50vw);
}

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

html {
  /* No font-size override — respecting the user's browser setting is the whole
     point of moving off a scaled canvas. */
  -webkit-text-size-adjust: 100%;

  /* Absorbs the bleed overhang — see --bleed-inset. It has to be HERE and not
     only on body: `clip` is not one of the overflow values Chrome propagates
     from body up to the viewport (hidden/scroll/auto are), so the rule on body
     alone left the document scrollable ~7px sideways.

     `clip` rather than `hidden` on purpose: hidden makes this a scroll
     container, which would break position: sticky anywhere below it. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--white);
  color: var(--black);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

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

/* ---------------------------------------------------------------------------
   Site canvas.

   The design is a 1440-wide artboard, so the site caps there and centres on
   white above it rather than stretching the bands and curves indefinitely.

   container-type: inline-size is what makes that safe. Every comp-derived
   offset in sections.css is expressed in `cqw` — a percentage of THIS box —
   not `vw`. With viewport units those offsets would keep growing past 1440
   while the content stopped, so paddings and overlaps would drift wider and
   wider on a large monitor. Against the container they simply stop at their
   comp values, and below 1440 the container is the viewport so they still
   scale exactly as before.
   --------------------------------------------------------------------------- */
.site {
  max-width: calc(var(--design-w) * 1px);
  margin-inline: auto;
  container-type: inline-size;
}

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

.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* The inner pages are drawn on a wider column than the homepage: their content
   runs 181 -> 1259 (1078) where the homepage runs 192.5 -> 1247.5 (1055). Set
   on .site so every .wrap inside inherits it, including those in the shared
   header and footer partials. The build adds .site-inner to any themed page. */
.site-inner {
  --wrap: 1078px;
}

/* ---------------------------------------------------------------------------
   Full bleed.

   Escapes the 1440 canvas so an element spans the viewport. `50%` resolves
   against the capped .site, `50vw` against the viewport, so the two cancel to
   exactly the white margin on each side.

   This is why .site keeps its cap rather than simply going full width: the cap
   is what makes it the container for `cqw`, and every comp-derived offset in
   sections.css is expressed in those units. Uncapping .site would re-inflate
   all of them — 78% larger at 2560 — which is the drift the container was
   introduced to stop. Bleeding individual elements leaves that geometry frozen.

   Only ever apply this to elements with no percentage-positioned children.
   The bands are the counter-example: .daisy-1 sits at `left: 10.66%` OF ITS
   BAND, so widening the band flings the decorations apart. Bands therefore keep
   their 1440 box and bleed their BACKGROUND via a pseudo-element instead.

   `100vw` includes the scrollbar, so a bleed element overhangs ~7.5px each
   side. body { overflow-x: clip } absorbs it — no horizontal scrollbar — and
   at these widths it is well under a percent of the element. */
/* max-width: none is not optional on either of these. `img, svg, video` above
   sets max-width: 100%, which silently clamps a bleeding IMG back to its
   parent's width — the bleed then does nothing at all above 1440, while still
   looking correct below it, where 100vw and 100% are nearly the same number. */
.bleed {
  width: 100vw;
  max-width: none;
  margin-inline: var(--bleed-inset);
}

/* The same escape for artwork that is already absolutely positioned inside a
   band — dividers and arc hairlines, which set `left: 0; width: 100%`. */
.bleed-abs {
  left: var(--bleed-inset);
  width: 100vw;
  max-width: none;
}

/* Every band is a positioning context for its own decorative backdrop, and
   clips it, so curves never leak into the neighbouring section. */
.band {
  position: relative;
  isolation: isolate;
}

/* Backdrops scale with their band and never intercept pointer events or
   screen-reader attention. */
.band > .backdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}

.band > .wrap {
  position: relative;
}

/* Decorative vectors: positioned as a percentage of their band so they track
   the artwork as it scales, rather than sitting at fixed pixel offsets. */
.deco {
  position: absolute;
  pointer-events: none;
  z-index: -1;
}

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

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------------------------------------------------------------------------
   Decoration motion — subtle daisy / floral rotation.

   Two rotations on the homepage daisies (.deco.daisy) and the inner-page
   florals (.page-deco), split across two properties so they compose:
     1. LOAD  — one 360deg spin over 4.5s on load, here in CSS on the `rotate`
        property.
     2. SCROLL — a subtle rotation as the element travels the viewport, driven
        by JS in scripts.html on the `transform` property. JS rather than a
        pure-CSS scroll timeline because scroll-driven animations are absent in
        older Safari/Firefox; the JS runs everywhere and reuses the page's
        prefers-reduced-motion guard.

   Gated on `no-preference`: the reduce block above only clamps time-based
   durations. transform-origin is set here so the JS rotation pivots on centre;
   both the load spin and the scroll JS are suppressed under reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes daisy-load-spin {
    from { rotate: 0deg; }
    to   { rotate: 360deg; }
  }
  .deco.daisy,
  .page-deco {
    animation: daisy-load-spin 4.5s ease-out both;
    transform-origin: center;
  }
}

/* Screen-reader-only heading, so a section can be labelled without the label
   appearing in a design that does not draw one. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
