/* ==========================================================================
   Cashmere Marketing — the brand layer.

   Built against client-projects/cashmere/mobile-first-spec.md (12 Aug 2026).
   Mobile first: every rule below is the 375px rule until a min-width says
   otherwise. Colours are token references only — no raw hex in this file.
   ========================================================================== */

/* --- Self-hosted Open Sans, latin subset only ----------------------------
 * ONE weight (300), ONE family, latin only — 13KB against three Google-CDN
 * families on her current site. ⚠ Requesting a SINGLE weight from Google
 * returns a tighter subset than slicing a two-weight request: the same face
 * came back at 42KB when 300 and 400 were fetched together. Ask for exactly
 * what you ship. `swap` so copy paints immediately; preload in inc/site.php.
 */
@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 300;
    font-display: swap;
    src: url('../fonts/open-sans-300-latin.woff2') format('woff2');
}

/* --- The ground ----------------------------------------------------------
 * `color-scheme: dark` tells the browser the page is intentionally dark, so
 * form controls, scrollbars and any forced-dark extension behave rather than
 * inverting a dark design into an illegible one. Spec § failure mode 5.
 */
:root { color-scheme: dark; }

body {
    background: var(--td-color-background);
    color: var(--td-color-text);
    font-weight: 300;
    letter-spacing: 0.01em;
}

::selection { background: var(--td-c-gold); color: var(--td-c-black); }

/* Focus ring — gold, offset, never removed. Accessibility floor. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--td-color-link);
    outline-offset: 3px;
}

/* --- Layout --------------------------------------------------------------
 * The brand is spare and the emptiness is the design. Generous vertical
 * rhythm, content centred, and NOTHING added at wide viewports to fill space.
 */
/* ⚠ NO min-height: 100svh HERE, DELIBERATELY.
 * It was forcing the hero block to fill the viewport, which pushed the form
 * entirely below the fold on every laptop. The brief is that the top of the
 * form must be visible on load at standard laptop sizes, so the page is sized
 * by its content and the rhythm is tuned to fit — measured, not guessed.
 */
.td-main {
    padding: var(--td-space-lg) var(--td-space-md) var(--td-space-xl);
}

.td-page_body { margin: 0 auto; max-width: 34rem; }

.td-module { margin-left: auto; margin-right: auto; text-align: center; }

.td-prose { max-width: none; }            /* centred short copy, not a reading column */

/* --- Type ----------------------------------------------------------------
 * Two short lines of copy carry the whole page, so they are display type,
 * not body type. Letterspaced to echo the wordmark inside the logo.
 */
.td-module--text .td-prose p {
    font-size: clamp(1rem, 4vw, 1.25rem);
    font-weight: 300;
    line-height: 1.55;
    letter-spacing: 0.055em;
    color: var(--td-color-text);
    margin: 0;
}

/* The page needs one h1 for machines. Her design does not want to show it —
   the logo IS the mark — so it is available to assistive tech and search and
   invisible on screen. Not display:none, which screen readers also skip. */
.td-page_title {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --- The logo ------------------------------------------------------------
 * The above-fold anchor and the site's only visual. Capped hard so the
 * browser never pulls a variant larger than it can use — the source is
 * 2560px wide and the rendered width here is a tenth of that.
 */
.td-module--image { margin-block: var(--td-space-md); }

.td-module--image img {
    width: min(225px, 62vw);
    height: auto;
    margin: 0 auto;
}

/* --- Footer --------------------------------------------------------------
 * Deliberately quiet. `--td-color-text-muted` is 4.1:1 and therefore LARGE
 * TEXT AND UI ONLY — the copyright line sits at the meta size, so it uses the
 * body grey instead. Keeping the muted token unused here on purpose.
 */
.td-footer {
    padding: var(--td-space-lg) var(--td-space-md);
    text-align: center;
    border-top: 1px solid var(--td-color-border);
}

.td-footer_copyright {
    margin: 0;
    font-size: var(--td-size-meta);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--td-color-text);
}

.td-header { display: none; }              /* one page, no nav — spec § navigation */

/* --- Forms ---------------------------------------------------------------
 * Forminator markup, overridden to the brand. Single column at EVERY
 * viewport; ≥16px inputs so iOS does not zoom the page on focus.
 */
.forminator-ui .forminator-row,
.forminator-ui .forminator-col { width: 100% !important; float: none !important; }

.forminator-ui input[type="text"],
.forminator-ui input[type="email"],
.forminator-ui textarea {
    /* ⚠ Same Forminator specificity trap as the submit button — its own
     * (0,4,0) rule sets the field height and beat this one, rendering inputs
     * at 41px against the spec's 44px touch-target floor. Forced. */
    width: 100%;
    min-height: 48px !important;
    padding: var(--td-space-sm) !important;
    font-family: var(--td-font-body);
    font-size: 16px !important;            /* ⚠ below 16px, iOS zooms on focus */
    color: var(--td-color-heading);
    background: var(--td-color-surface);
    border: 1px solid var(--td-color-border);
    border-radius: var(--td-radius);
}

.forminator-ui textarea { min-height: 8rem; resize: vertical; }

.forminator-ui label {
    display: block;
    margin-bottom: var(--td-space-xs);
    font-size: var(--td-size-meta);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--td-color-text);
}

/* --- Motion --------------------------------------------------------------
 * Smooth scroll is the only motion on the page, and it is opt-out.
 */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}

/* --- Scale up ------------------------------------------------------------
 * Tablet and desktop grow the logo and the rhythm. Nothing is ADDED, and no
 * columns appear — see the spec's scale-up note.
 */
/* ⚠ THE VERTICAL BUDGET IS THE CONSTRAINT ON THIS PAGE, not the aesthetics.
 * The brief: the top of the form must be visible on load at any standard
 * laptop. The tightest common case is a 1366×768 screen, which is roughly a
 * 620px viewport after browser chrome. Every value below was set by measuring
 * against that, not by eye. Changing the logo size or the top padding moves
 * the form — re-measure before shipping either.
 */
@media (min-width: 48em) {
    .td-main { padding: var(--td-space-lg) var(--td-space-lg) var(--td-space-xl); }
    .td-page_body { max-width: 36rem; }
    .td-module--image img { width: 255px; }
    .td-module--text:has(form) { margin-top: var(--td-space-sm); }
}

@media (min-width: 64em) {
    .td-page_body { max-width: 38rem; }
    .td-module--image img { width: 270px; }
    .td-module--text .td-prose p { letter-spacing: 0.07em; }
}

/* --- The contact section -------------------------------------------------
 * The CTA scrolls here. scroll-margin keeps the heading clear of the viewport
 * edge on arrival — without it the anchor lands flush against the top and the
 * heading reads as cut off.
 */
/* ⚠ TARGETED BY CONTENT, NOT BY ID. The module's id comes from its heading
 * text, so styling hooked to .td-module--text:has(form) broke the moment the heading changed
 * from "Contact" to "Start a conversation". :has(form) asks the question that
 * actually matters — "the module holding the form" — and survives any rewording.
 */
.td-module--text:has(form) {
    scroll-margin-top: var(--td-space-lg);
    margin-top: var(--td-space-sm);
    text-align: left;
}

.td-module--text:has(form) .td-module_heading {
    margin: 0 0 var(--td-space-md);
    font-size: var(--td-size-meta);
    font-weight: 400;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--td-color-text-muted);
    text-align: center;
}

/* --- Forminator, brought into the brand -----------------------------------
 * ⚠ Forminator ships its own button, input and error styling at a specificity
 * that beats plain class selectors. These rules are scoped under .td-module--text:has(form) and
 * still need the plugin's own selectors named — a generic `button {}` does not
 * reach them.
 */
.td-module--text:has(form) .forminator-button-submit,
.td-module--text:has(form) button[type="submit"] {
    /* ⚠ !important ON THE SIZING PROPERTIES IS LOAD-BEARING, NOT LAZY.
     *
     * Forminator's own rule is
     *   .forminator-ui.forminator-custom-form[data-design="default"] .forminator-button
     * — two classes, an attribute and a class: specificity (0,4,0). This
     * selector scores (0,2,1), because :has() contributes only the weight of
     * its argument (`form`, an element). So min-height, padding, border and
     * width ALL silently lost, and the button rendered at 40px — under the
     * 44px touch-target floor the mobile-first spec sets. Background and
     * colour won only because Forminator sets those in a weaker rule.
     *
     * Raising specificity by matching their shape would mean writing
     * [data-design="default"] into this file and depending on a plugin
     * internal. Targeted !important is the honest, stable answer.
     */
    display: block !important;
    width: 100% !important;
    min-height: 48px !important;
    margin-top: var(--td-space-md);
    padding: 0 var(--td-space-lg) !important;
    background: var(--td-color-link);
    border: 1px solid var(--td-color-link) !important;
    border-radius: var(--td-radius);
    color: var(--td-c-black);
    font-family: var(--td-font-body);
    font-size: var(--td-size-ui);
    font-weight: 400;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color var(--td-transition), background-color var(--td-transition), border-color var(--td-transition);
}

.td-module--text:has(form) .forminator-button-submit:hover,
.td-module--text:has(form) button[type="submit"]:hover,
.td-module--text:has(form) .forminator-button-submit:focus-visible,
.td-module--text:has(form) button[type="submit"]:focus-visible {
    background: var(--td-color-link-hover);
    border-color: var(--td-color-link-hover);
    color: var(--td-c-black);
}

/* ⚠ The submit is the page's ONLY primary action, so it is filled at rest —
 * an outline button reads as secondary, and there is nothing for it to be
 * secondary to. Black on gold measures the same 6.93:1 as gold on black. */

/* The required marker is red by default — the only saturated colour on an
   otherwise gold-and-grey page. The asterisk carries the meaning; the colour
   was never doing the work.
 *
 * ⚠ WHY !important HERE, AND ONLY HERE. Forminator's own rule is
 *   .forminator-ui#forminator-module-N.forminator-design--default
 *     .forminator-label .forminator-required
 * — one ID plus four classes, specificity (1,4,0), against (1,1,0) for an ID
 * anchor alone. Matching its shape would mean writing #forminator-module-8
 * into this file, and THAT NUMBER CHANGES if the form is ever rebuilt: the
 * style would silently stop applying and nothing would say why.
 *
 * So the override is one declaration, scoped under #contact, marked important
 * on purpose. Do not widen it. */
.td-module--text:has(form) .forminator-required,
.td-module--text:has(form) .forminator-label .forminator-required {
    color: var(--td-color-text-muted) !important;
}

/* Field spacing — Forminator's own row margins are tuned for its default
   theme, not for a page this sparse. */
.td-module--text:has(form) .forminator-row { margin-bottom: var(--td-space-md); }
.td-module--text:has(form) .forminator-field { margin: 0; }

/* Validation and success messages inherit the palette rather than the
   plugin's greens and reds. */
.td-module--text:has(form) .forminator-response-message {
    margin-top: var(--td-space-md);
    padding: var(--td-space-sm);
    background: var(--td-color-surface);
    border: 1px solid var(--td-color-border);
    color: var(--td-color-text);
}

/* --- Contact form: Turnstile ------------------------------------------
 * The Turnstile key runs in invisible mode, so the widget row is hidden and
 * the note under the form discloses it (Cloudflare's ask for invisible use).
 * Mirrors RDCM's .rdcm-turnstile-note. Added 2026-09-02.
 */
.forminator-ui .forminator-field-captcha { display: none; }
.forminator-ui .forminator-row:has(.forminator-field-captcha) { display: none; }

.td-turnstile-note {
    margin: var(--td-space-sm) 0 0;
    font-size: var(--td-size-meta);
    color: var(--td-color-text);
}
