/* ==========================================================================
   Palm Estate - base stylesheet
   --------------------------------------------------------------------------
   Reset, typography defaults and layout primitives. Every value here comes
   from a token in style.css.

   01 Fonts
   02 Reset
   03 Base elements
   04 Typography
   05 Layout: containers and sections
   06 Utilities
   07 Accessibility
   08 Breakpoints
   ========================================================================== */


/* 01 Fonts ================================================================= */

/*
 * Both families are self-hosted: no third-party connection on the critical
 * path, which matters for the LCP target. Jost is OFL licensed, so hosting it
 * is permitted.
 *
 * Jost ships as a variable font, so one file covers 300-600 instead of four
 * static weights. Put jost-variable.woff2 in assets/fonts/ - the easiest
 * source is `npm i @fontsource-variable/jost` (files land in
 * node_modules/@fontsource-variable/jost/files/) or google-webfonts-helper.
 */
@font-face {
	font-family: 'Jost';
	src: url('../fonts/jost-variable.woff2') format('woff2');
	font-weight: 300 600;
	font-style: normal;
	font-display: swap;
}

/*
 * The display serif is a client blocker: the name is still TBC from Figma and
 * the licensed woff2 has not been delivered. Uncomment this block and drop the
 * files in assets/fonts/ when they arrive, then the 'Palm Serif' family in
 * --font-display resolves and every heading picks it up with no other change.
 *
 * Left commented rather than active so the build does not 404 on a missing
 * font file on every page load in the meantime.
 *
 * @font-face {
 *   font-family: 'Palm Serif';
 *   src: url('../fonts/palm-serif.woff2') format('woff2');
 *   font-weight: 400;
 *   font-style: normal;
 *   font-display: swap;
 * }
 *
 * @font-face {
 *   font-family: 'Palm Serif';
 *   src: url('../fonts/palm-serif-italic.woff2') format('woff2');
 *   font-weight: 400;
 *   font-style: italic;
 *   font-display: swap;
 * }
 */


/* 02 Reset ================================================================= */

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

/* Strip the margins the browser invents, then reintroduce spacing
   deliberately through the spacing scale. */
body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd,
ul, ol, fieldset, legend {
	margin: 0;
	padding: 0;
}

/* The hidden attribute always wins. The browser's own [hidden] rule loses to
   any component that sets display: flex or grid, so without this, scripts
   that hide things with el.hidden - listing cards, the pager, the filter bar
   before its script runs - would silently stop hiding them. */
[hidden] {
	display: none !important;
}

/* Only lists that carry a class are treated as UI; content lists in the
   editor keep their markers. */
ul[class],
ol[class] {
	list-style: none;
}

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

	/* Anchor jumps should not land underneath the floating fixed header. */
	scroll-padding-top: calc(var(--header-h) + var(--header-offset));
}

/* Smooth scroll, but never for people who have asked the OS to stop
   animating things. */
@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

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

::selection {
	background-color: var(--pe-accent);
	color: var(--pe-text-on-accent);
}


/* 03 Base elements ========================================================= */

body {
	background-color: var(--pe-bg);
	color: var(--pe-text);
	font-family: var(--font-body);
	font-size: var(--fs-base);
	font-weight: 400;
	line-height: var(--lh-base);
	min-height: 100vh;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

/* Media behaves as blocks and never overflows its column. */
img,
picture,
video,
canvas,
svg {
	display: block;
	max-width: 100%;
}

img,
video {
	height: auto;
}

/* Inherit type into form controls instead of falling back to the UA font. */
input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

button {
	background: none;
	border: 0;
	cursor: pointer;
}

a {
	color: var(--pe-accent);
	text-decoration-thickness: var(--hairline);
	text-underline-offset: 0.2em;
	transition: color var(--dur-fast) var(--ease);
}

a:hover,
a:focus-visible {
	color: color-mix(in srgb, var(--pe-accent) 75%, var(--pe-ink));
}

hr {
	height: 0;
	margin-block: var(--space-lg);
	border: 0;
	border-top: var(--hairline) solid var(--pe-rule);
}

table {
	border-collapse: collapse;
	width: 100%;
}


/* 04 Typography ============================================================ */

/* Headings run on the display serif. Sizes are assigned by level here; a
   heading that needs a different size takes a utility rather than a new rule. */
h1, h2, h3, h4, h5, h6 {
	font-family: var(--font-display);
	font-weight: 400;
	line-height: var(--lh-snug);
	letter-spacing: var(--ls-tight);
	text-wrap: balance;
}

h1 {
	font-size: var(--fs-3xl);
	line-height: var(--lh-tight);
}

h2 {
	font-size: var(--fs-2xl);
}

h3 {
	font-size: var(--fs-xl);
}

h4 {
	font-size: var(--fs-lg);
	letter-spacing: var(--ls-normal);
}

h5,
h6 {
	font-size: var(--fs-md);
	letter-spacing: var(--ls-normal);
}

/* The hero and CTA headlines, larger than any document heading level. */
.display {
	font-family: var(--font-display);
	font-size: var(--fs-display);
	font-weight: 400;
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-tight);
	text-wrap: balance;
}

/* Second line of a headline, in italic. Used on the hero and on the market
   edge and CTA blocks. */
.display em,
h1 em,
h2 em {
	font-style: italic;
}

p {
	max-width: var(--measure);
	text-wrap: pretty;
}

/* Flow spacing: the gap belongs between siblings, not hanging off the last
   one. */
p + p,
p + ul,
p + ol,
ul + p,
ol + p {
	margin-top: var(--space-sm);
}

h1 + p,
h2 + p,
h3 + p,
h4 + p {
	margin-top: var(--space-md);
}

p + h2,
p + h3,
ul + h2,
ul + h3 {
	margin-top: var(--space-xl);
}

/* Lead paragraph: hero sub copy, section intros. */
.lead {
	font-size: var(--fs-lg);
	font-weight: 300;
	line-height: var(--lh-loose);
	max-width: var(--measure-narrow);
}

strong,
b {
	font-weight: 500;
}

small {
	font-size: var(--fs-sm);
}

blockquote {
	font-family: var(--font-display);
	font-size: var(--fs-xl);
	font-style: italic;
	line-height: var(--lh-snug);
	max-width: var(--measure-narrow);
}

/* Prose lists only - the ones an editor writes, which carry no class. A list
   with a class is a component (nav, grids, card specs) and lays itself out;
   giving those an indent and a margin between items shifted real layouts: the
   first nav item sat 2px above the rest, grid cards after the first 4px low,
   and journey waypoints 2 to 4 4px off their computed points. Same principle
   as list-style in section 02. */
ul:not([class]),
ol:not([class]) {
	padding-left: 1.2em;
}

ul:not([class]) > li + li,
ol:not([class]) > li + li {
	margin-top: var(--space-3xs);
}


/* 05 Layout: containers and sections ======================================= */

/*
 * .container is the only thing that sets horizontal padding. Sections own
 * their background and vertical rhythm, so a full-bleed colour band wraps a
 * container rather than being one.
 */
.container {
	width: 100%;
	max-width: var(--container-max);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

/* Never wider than the standard container, which from tablet width up is
   proportional and can be the narrower of the two. */
.container--narrow {
	max-width: min(var(--container-narrow), var(--container-max));
}

.container--text {
	max-width: min(var(--container-text), var(--container-max));
}

/* Full-bleed inside a container: images and the journey canvas. */
.container--flush {
	max-width: none;
	padding-inline: 0;
}

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

.section--tight {
	padding-block: var(--space-xl);
}

/* Colour bands. Text colour flips with the ground so nothing downstream has
   to remember to. */
.section--forest,
.section--pine,
.section--deep {
	color: var(--pe-text-on-dark);
}

.section--forest {
	background-color: var(--pe-bg-dark);
}

.section--pine {
	background-color: var(--pe-surface-dark);
}

.section--deep {
	background-color: var(--pe-bg-darkest);
}

.section--cream {
	background-color: var(--pe-bg);
	color: var(--pe-text);
}

/* Links and rules on a dark ground. */
.section--forest a,
.section--pine a,
.section--deep a {
	color: var(--pe-accent);
}

.section--forest hr,
.section--pine hr,
.section--deep hr {
	border-top-color: var(--pe-rule-on-dark);
}


/* 06 Utilities ============================================================= */

/* Small-caps label: BUY / SELL / INVEST / STAY, eyebrows, the trust line,
   form labels, role lines. The most-reused text treatment in the design. */
.u-caps {
	font-family: var(--font-body);
	font-size: var(--fs-2xs);
	font-weight: 500;
	letter-spacing: var(--ls-caps);
	line-height: var(--lh-snug);
	text-transform: uppercase;
}

.u-caps--accent {
	color: var(--pe-accent);
}

.u-center {
	text-align: center;
}

.u-center-block {
	margin-inline: auto;
}

/* Cancel the default measure where a block is meant to run full width. */
.u-measure-none {
	max-width: none;
}

.u-measure-narrow {
	max-width: var(--measure-narrow);
}

.u-accent {
	color: var(--pe-accent);
}

.u-muted {
	color: var(--pe-text-muted);
}

/* Hairline divider that inherits the right colour for its ground. */
.u-rule {
	border: 0;
	border-top: var(--hairline) solid currentColor;
	opacity: 0.18;
}


/* 07 Accessibility ========================================================= */

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

.skip-link:focus {
	position: fixed;
	top: var(--space-2xs);
	left: var(--space-2xs);
	z-index: var(--z-skip);
	width: auto;
	height: auto;
	clip: auto;
	clip-path: none;
	padding: var(--space-xs) var(--space-sm);
	background-color: var(--pe-bg);
	color: var(--pe-text);
	border: 2px solid var(--pe-accent);
}

/* One focus treatment for the whole build. Bronze reads on both grounds. */
:focus-visible {
	outline: 2px solid var(--pe-accent);
	outline-offset: 3px;
}

/* Only suppress the default ring where :focus-visible is supported, so older
   engines keep a visible focus state. */
@supports selector(:focus-visible) {
	:focus:not(:focus-visible) {
		outline: none;
	}
}


/* 08 Breakpoints =========================================================== */

/*
 * The three project breakpoints: 1024 / 768 / 480.
 *
 * These are written as literals because a custom property cannot be used in a
 * media condition - `@media (max-width: var(--bp-md))` is invalid and the
 * browser drops the entire block silently. --bp-lg / --bp-md / --bp-sm in
 * style.css are the documented copy and what JS reads; if one changes, change
 * both.
 *
 * The blocks are deliberately thin. Type, gutter and section rhythm already
 * scale continuously through clamp(), so only values that genuinely step
 * rather than flow belong here. Components add their own media blocks in
 * their own phase; this section owns the global tokens.
 */

/*
 * The header height, offset and width are fluid in style.css with their own
 * floors, so they no longer step here. lg (1024) and sm (480) currently have
 * nothing to step; the blocks return when a component needs them.
 */

/* md - the layout stacks and the primary nav becomes the Phase 02 overlay. */
@media (max-width: 768px) {
	:root {
		/* Full desktop section rhythm eats too much of a short viewport. */
		--space-section: clamp(3rem, 9vw, 5rem);
	}
}

/*
 * From tablet width up the page is proportional, as the design is: every
 * section's content spans 71% of the viewport, whatever the viewport, with
 * the rest as margin. The container's max-width includes its own gutters, so
 * they are added back on. Capped at 90rem of content so an ultra-wide screen
 * does not stretch a section's copy past reading width. Below this the
 * container is simply the viewport less its gutters.
 */
@media (min-width: 768px) {
	:root {
		--container-max: min(calc(71vw + 2 * var(--gutter)), calc(90rem + 2 * var(--gutter)));
	}
}
