/* ==========================================================================
   tokens.css — SOURCE. Decorator build, Direction A "Colour Card".
   Brand block below is project-specific. The two alias blocks under it
   are kit-required — names stay, only values change.
   ========================================================================== */

:root {
  /* ============ BRAND TOKENS — Colour Card ============
     Named like a heritage paint chart on purpose: the palette IS the
     subject. Sofa Taupe / Greige exist only for the swatch tabs.
     All values sampled from the hero photo. */
  --ink:          #2d2b28;   /* Rug Charcoal */
  --paper:        #f2eee8;   /* Mist Coat */
  --paper-alt:    #e4dcd3;   /* Picture Rail */
  --accent-raw:   #2f6b55;   /* Panel Green */
  --accent-raw-hover: #255644;
  --muted:        #6f675e;
  --border-raw:   #d0c6ba;

  --swatch-1:     var(--accent-raw);  /* Panel Green */
  --swatch-2:     #8a6c58;            /* Sofa Taupe */
  --swatch-3:     #c2b7ab;            /* Greige */

  /* Young Serif ships weight 400 ONLY — components.css pins headings
     and buttons to 400 so the browser never synthesises a faux bold. */
  --font-display: 'Young Serif', Georgia, serif;
  --font-body:    'Schibsted Grotesk', system-ui, sans-serif;

  /* Paint chips are square-cut — no soft rounding on this build. */
  --radius:       0.125rem;
  --radius-lg:    0.25rem;

  /* ============ STRUCTURAL TOKENS — reusable as-is ============ */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.5rem;
  --space-6:  2rem;
  --space-7:  3rem;
  --space-8:  4rem;

  --container-max:   72rem;
  --container-pad:   clamp(1.5rem, 6vw, 5rem);
  --nav-height:       4.5rem;

  /* ============ REQUIRED ALIAS — base.css focus-ring depends on this ============ */
  --accent:        var(--accent-raw);
  --accent-hover:  var(--accent-raw-hover);

  /* ============ GENERIC ALIAS LAYER — powers admin.html / calendar-help.html ============ */
  --color-accent:        var(--accent);
  --color-accent-hover:  var(--accent-hover);
  --color-bg:            var(--paper);
  --color-bg-alt:        var(--paper-alt);
  --color-text:          var(--ink);
  --color-text-muted:    var(--muted);
  --color-border:        var(--border-raw);
  --color-white:         #ffffff;
  --color-error:         #b3261e;
  --color-success:       #15803d;

  --space-1-alt: var(--space-1); /* aliases kept 1:1 on purpose — */
  --text-sm:     0.875rem;       /* admin.html reads --text-sm directly */
}
/* ==========================================================================
   base.css — SOURCE. Reset + element defaults. Reusable as-is across
   every project — don't edit per client.
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Fix: sticky/fixed nav needs scroll-padding-top equal to its height,
     set once globally, or every anchor jump (native fragment nav,
     scrollIntoView, tab links) lands its target underneath the nav. */
  scroll-padding-top: var(--nav-height);
}

body {
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.15;
  font-weight: 600;
}

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

/* Opt-in, not opt-out: lists default to no markers because most lists
   in a landing page are nav/primitive lists, not real numbered/bulleted
   content. Pages with genuine step lists must opt back in explicitly
   per list (e.g. `ol.help-steps { list-style: decimal; }`) — otherwise
   the numbers silently vanish while the text still reads fine, which
   is easy to miss in review. */
ul, ol { list-style: none; padding: 0; }

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

button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }

/* Fix: some shared layout classes (e.g. .stack, .cluster) set
   display:flex on their own children — that silently beats the
   browser's own [hidden] { display:none } default on any element that
   also carries one of those classes. This override makes [hidden]
   actually win regardless of what else is applied alongside it. */
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* No skip-to-content link by default — these are simple one-pagers.
   Add one explicitly only if a specific project asks for it. */
/* ==========================================================================
   layout.css — SOURCE. Generic layout primitives. Reusable as-is,
   rarely needs edits. Before writing fresh flex/grid for a new section,
   check this file first.

   Canonical breakpoints, used everywhere in this file and components.css:
     max-width: 640px   mobile
     max-width: 960px   tablet & down
     min-width: 961px   desktop & up
   ========================================================================== */

.container {
  max-width: var(--container-max);
  margin-inline: auto;
  /* Fix: --container-pad has a clamp() floor in tokens.css so this
     never collapses to near-zero on narrow viewports. */
  padding-inline: var(--container-pad);
}

.section          { padding-block: var(--space-8); }
.section--alt     { background: var(--paper-alt); }
.section--dark    { background: var(--ink); color: var(--paper); }

.stack            { display: flex; flex-direction: column; }
.stack > * + *     { margin-top: var(--space-4); }
.stack--tight > * + * { margin-top: var(--space-2); }
.stack--loose > * + * { margin-top: var(--space-7); }
/* Fix: margin-top does nothing to inline elements. A footer link list
   built from bare <a> tags inside .stack collapses onto one line
   without this — markup is correct, display:inline just ignores
   margin-top. */
.stack > a        { display: block; }

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-7);
  align-items: center;
}
@media (max-width: 960px) {
  .split { grid-template-columns: 1fr; }
}

.grid-auto {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-6);
}

.grid-fixed-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
}
@media (max-width: 960px) {
  .grid-fixed-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .grid-fixed-3 { grid-template-columns: 1fr; }
}
/* ==========================================================================
   components.css — SOURCE. Nav/button/card/form/tab mechanics are
   reusable as-is. Colours, radius values, and the signature element
   are project-specific — replace those, keep the mechanics.
   ========================================================================== */

/* ---------- Nav ----------
   Fix: .nav__bar and .nav__panel are BOTH children of .nav__inner, a
   single shared flex row — not siblings of it. Splitting them as
   siblings under <header> misaligns the nav links from the logo/toggle
   the moment the panel opens. */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  border-bottom: 1px solid var(--border-raw);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--nav-height);
  position: relative; /* .nav__panel anchors to this */
}
.nav__logo {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.1rem;
}
.nav__bar {
  display: none;
  gap: var(--space-6);
}
.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: none;
  border: none;
  font-weight: 600;
}
.nav__panel {
  display: none;
  flex-direction: column;
  gap: var(--space-1);
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--paper);
  border-bottom: 1px solid var(--border-raw);
  padding: var(--space-4) 0;
}
.nav__panel.is-open { display: flex; }
/* Fix: a nav CTA button reusing full .btn styling can collide with
   .nav__panel's own link styling depending on load order/specificity.
   Scoping plain nav links to :not(.btn) keeps the CTA button looking
   like a button regardless. */
.nav__panel a:not(.btn) {
  padding: var(--space-2) var(--container-pad);
  font-weight: 500;
}
.nav__panel .btn { margin-inline: var(--container-pad); }

@media (min-width: 961px) {
  .nav__bar { display: flex; align-items: center; }
  .nav__toggle { display: none; }
  .nav__panel { display: none !important; }
}

/* ---------- Buttons ----------
   Fix: inline-flex without justify-content:center pins a full-width
   button's label to the left in a flex column. Centering is part of
   the default, not something each variant re-adds. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius);
  font-weight: 600;
  border: 1.5px solid transparent;
  text-align: center;
}
.btn--primary {
  background: var(--accent);
  color: var(--color-white);
}
.btn--primary:hover { background: var(--accent-hover); }
.btn--outline {
  background: transparent;
  border-color: var(--border-raw);
  color: var(--ink);
}
.btn--block { width: 100%; }

/* ---------- Cards ----------
   Fix: an offset "behind" shape using a second independently-curved
   element (its own per-corner border-radius) doesn't stay a constant
   distance from the card if box size or curvature differs even
   slightly — the two curves cross at the corners and leak a hairline
   of the background colour through anti-aliasing. A single box-shadow
   on the card itself gives the same offset/shadow effect with nothing
   to keep in geometric sync. Swap the colour/offset per project;
   don't reintroduce a second shape. */
.card {
  background: var(--color-white);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: 0.4rem 0.4rem 0 var(--accent);
}

/* ---------- Forms ----------
   Fix: inputs/textareas inside a flex or grid layout size to their own
   intrinsic width by default, not their column — width:100% plus
   min-width:0 (to guard against overflow in a tight grid track) is
   required on every field, not assumed. */
.field { margin-bottom: var(--space-4); }
.field label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: var(--space-2);
}
.field input,
.field textarea,
.field select {
  width: 100%;
  min-width: 0;
  padding: var(--space-3);
  border: 1.5px solid var(--border-raw);
  border-radius: var(--radius);
  background: var(--color-white);
}
.field input:focus,
.field textarea:focus { outline: none; border-color: var(--accent); }
.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}
@media (max-width: 640px) {
  .field-row { grid-template-columns: 1fr; }
}

/* ---------- Tabs ----------
   Fix (progressive enhancement): content hidden via [hidden] is
   unreachable with no JS and no fallback. Panels are visible (stacked)
   by default; only .js — added by an inline script at the very top of
   <head>, before anything else runs — gates the collapse to a tab
   view. This uses its own class rather than the [hidden] attribute so
   it doesn't collide with base.css's global [hidden] override. */
.tabs__list { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-5); }
.tabs__tab {
  padding: var(--space-2) var(--space-4);
  border-radius: 999px;
  border: 1.5px solid var(--border-raw);
  background: var(--color-white);
  font-weight: 600;
  font-size: 0.9rem;
}
.tabs__tab[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--color-white);
}
.tab-panel + .tab-panel { margin-top: var(--space-6); }
/* Nav/anchor jumps to a panel land it flush under the sticky nav
   (scroll-padding-top only clears the nav itself). This adds
   breathing room above the panel's heading on arrival. */
.tab-panel { scroll-margin-top: var(--space-6); }
.js .tab-panel:not(.is-active) { display: none; }

/* ---------- Scroll reveal ----------
   Fix: a hidden starting state set unconditionally in CSS
   ([data-reveal]{opacity:0}) means that if the driving script ever
   fails to run, the content is gone permanently — including, on a
   past build, an entire hero headline. The script adds its own
   .reveal-pending class before animating; the [data-reveal] attribute
   alone does nothing visually. */
.reveal-pending { opacity: 0; transform: translateY(1rem); }
.reveal-pending.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s ease, transform 0.5s ease;
}


/* ==========================================================================
   PROJECT LAYER — Decorator, Direction A "Colour Card".
   Everything below is this build's visual layer only. No kit mechanic
   above has been edited.
   ========================================================================== */

/* ---------- Young Serif weight lock ----------
   Young Serif ships 400 only. base.css sets h1–h4 to 600 and the kit
   logo is 600 — both would force faux-bold synthesis (same failure as
   Anton on Meal Deal). Pin anything set in the display face to 400. */
h1, h2, h3, h4,
.nav__logo { font-weight: 400; }

h1 { font-size: clamp(2.1rem, 5vw, 3.4rem); line-height: 1.05; }
h2 { font-size: clamp(1.6rem, 3.2vw, 2.3rem); }
h3 { font-size: 1.3rem; }

.eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.lede { color: var(--muted); max-width: 52ch; font-size: 1.05rem; }

.nav__bar a:not(.btn) { font-weight: 500; }

/* ---------- Full-width hero ----------
   Adapted from the holiday-home build's .hero-banner (1 Sept): one
   full-bleed <img>, no grid. Difference here is the structural risk —
   no gradient over the photo. The headline sits on a solid Mist Coat
   panel (.hero-card) that is pulled up over the bottom of the image
   with a negative margin and breaks into the page below, like a colour
   card held against a freshly painted wall. Normal document flow, no
   absolute positioning on the card, so its height can never collide
   with the next section. */
.hero-banner__img {
  width: 100%;
  height: clamp(18rem, 62vh, 38rem);
  object-fit: cover;
}
.hero-card {
  position: relative;
  z-index: 1;
  max-width: 38rem;
  margin-top: -8rem;
  background: var(--paper);
  padding: var(--space-6);
}
.hero-card > * + * { margin-top: var(--space-4); }
.hero-card .cluster { margin-top: var(--space-5); }
@media (max-width: 960px) {
  .hero-card { margin-top: -4rem; padding: var(--space-5); }
}

/* ---------- Swatch tabs (signature element, used once) ----------
   Overrides the kit's pill tabs for this group only (.tabs--swatch).
   Each tab is a paint chip: colour block on top, name + "No." code
   under it. Selected chip lifts with the kit's single box-shadow
   offset — no second shape behind it. Chip colour comes from
   --swatch-1/2/3 by position, so markup carries no inline styles. */
.tabs--swatch .tabs__list {
  flex-wrap: nowrap;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}
.tabs--swatch .tabs__tab {
  flex: 0 1 11rem;
  min-width: 0; /* lets three chips share 327px at 375 wide */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: left;
  padding: 0;
  border: 1px solid var(--border-raw);
  border-radius: var(--radius);
  background: var(--color-white);
  color: var(--ink);
  font-weight: 400;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.tabs--swatch .tabs__tab:nth-child(1) { --chip: var(--swatch-1); }
.tabs--swatch .tabs__tab:nth-child(2) { --chip: var(--swatch-2); }
.tabs--swatch .tabs__tab:nth-child(3) { --chip: var(--swatch-3); }
.swatch__chip {
  display: block;
  aspect-ratio: 4 / 3;
  background: var(--chip);
}
.swatch__name {
  font-family: var(--font-display);
  font-size: 1.05rem;
  line-height: 1.2;
  padding: var(--space-2) var(--space-3) 0;
}
.swatch__code {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  padding: var(--space-1) var(--space-3) var(--space-3);
}
.tabs--swatch .tabs__tab:hover { border-color: var(--ink); }
/* Beats the kit's filled-pill selected state on specificity. */
.tabs--swatch .tabs__tab[aria-selected="true"] {
  background: var(--color-white);
  border-color: var(--ink);
  color: var(--ink);
  transform: translate(-0.25rem, -0.25rem);
  box-shadow: 0.4rem 0.4rem 0 var(--ink);
}
/* No-JS: swatches still render (they just don't switch anything) and
   all three panels sit stacked below, each with its own heading. */
@media (max-width: 640px) {
  .tabs--swatch .tabs__list { gap: var(--space-3); }
  .tabs--swatch .tabs__tab { flex: 1 1 0; }
  .swatch__name { font-size: 0.95rem; padding-inline: var(--space-2); }
  .swatch__code { padding-inline: var(--space-2); font-size: 0.6rem; }
}

.panel-head { margin-bottom: var(--space-6); }
.panel-head > * + * { margin-top: var(--space-3); }

/* ---------- Recent work ---------- */
.work-item img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius);
}
.work-item figcaption {
  margin-top: var(--space-3);
  font-size: 0.9rem;
  color: var(--muted);
}
.work-item figcaption strong {
  display: block;
  color: var(--ink);
  font-weight: 600;
}

/* ---------- FAQ list ---------- */
.faq-list { max-width: 46rem; }
.faq-list > div {
  padding-block: var(--space-5);
  border-top: 1px solid var(--border-raw);
}
.faq-list > div:last-child { border-bottom: 1px solid var(--border-raw); }
.faq-list h3 { margin-bottom: var(--space-2); }
.faq-list p { color: var(--muted); }

/* ---------- Contact details ---------- */
.contact-details > div > span {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.contact-details a { text-decoration: underline; text-underline-offset: 0.2em; }

/* ---------- Footer ---------- */
.site-footer a { opacity: 0.85; }
.site-footer a:hover { opacity: 1; }