/* ==========================================================================
   Ebanisteria Rosado — styles.css  (Phase 1: design foundations, final)
   Sections: 1 Fonts · 2 Tokens · 3 Base · 4 Type · 5 Layout · 6 Paper, ruler, dimension line
             7 Buttons · 8 Header & menu · 9 Hero, themes & section head · 10 Categories
             11 Gallery & lightbox · 12 Forms · 13 Footer · 13b Closing CTA band
             13c Next-category band · 13d Cookie banner · 14 Motion · 15 A11y
   ========================================================================== */

/* ---------- 1. Fonts (self-hosted, latin subset, WOFF2) ---------- */
@font-face {
  font-family: "Faculty Glyphic";
  src: url("fonts/faculty-glyphic-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Figtree";
  src: url("fonts/figtree-latin-wght.woff2") format("woff2");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
/* Fallbacks tuned to the real metrics so the font swap causes no layout shift */
@font-face {
  font-family: "Faculty Glyphic Fallback";
  src: local("Arial"), local("Liberation Sans"), local("Helvetica");
  size-adjust: 103.34%;
  ascent-override: 100.35%;
  descent-override: 25.35%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Figtree Fallback";
  src: local("Arial"), local("Liberation Sans"), local("Helvetica");
  size-adjust: 100.03%;
  ascent-override: 94.97%;
  descent-override: 24.99%;
  line-gap-override: 0%;
}

/* ---------- 2. Tokens ---------- */
:root {
  color-scheme: light dark;

  /* Fonts */
  --font-display: "Faculty Glyphic", "Faculty Glyphic Fallback", system-ui, sans-serif;
  --font-body: "Figtree", "Figtree Fallback", system-ui, sans-serif;

  /* Brand: exact logo coral. Decoration, big display text, and buttons with dark ink only. */
  --brand: #f64c3f;
  --on-brand: #201a18;

  /* Colour roles (light, dark). Tonal palettes generated from the brand seed. */
  --primary: light-dark(#c00016, #ffb4a7);
  --on-primary: light-dark(#ffffff, #690003);
  --primary-container: light-dark(#ffdad4, #3b1114);
  --on-primary-container: light-dark(#3a0a00, #ffdad4);
  --secondary: light-dark(#7e553b, #eebc9e);
  --on-secondary: light-dark(#ffffff, #4a2810);
  --secondary-container: light-dark(#fedcc7, #643e25);
  --on-secondary-container: light-dark(#2d1600, #fedcc7);
  --tertiary: light-dark(#3e646a, #a5ced4);
  --on-tertiary: light-dark(#ffffff, #0c363b);
  --tertiary-container: light-dark(#c1eaf0, #264c52);
  --on-tertiary-container: light-dark(#002024, #c1eaf0);
  --bg: light-dark(#fef8f5, #160f0c);
  --on-bg: light-dark(#201a18, #e9e1dd);
  --surface-lowest: light-dark(#ffffff, #000000);
  --surface-low: light-dark(#faf2ee, #201a18);
  --surface: light-dark(#f4ece9, #2a2522);
  --surface-high: light-dark(#efe6e3, #352f2c);
  --surface-highest: light-dark(#e9e1dd, #403a37);
  --on-surface: light-dark(#201a18, #e9e1dd);
  --on-surface-variant: light-dark(#52443d, #d5c3bb);
  --outline: light-dark(#84746c, #9e8d86);
  --outline-variant: light-dark(#d5c3bb, #52443d);
  /* Error: never colour alone (icon + text). Distinct from the brand red by hue. */
  --error: light-dark(#ba1a1a, #ffb4ab);
  --on-error: light-dark(#ffffff, #690005);
  --error-container: light-dark(#ffdad6, #93000a);
  --on-error-container: light-dark(#410002, #ffdad6);
  --success: light-dark(#1f6b3a, #8fd9a0);
  --success-container: light-dark(#d4f2dc, #0f3a1e);
  --on-success-container: light-dark(#06210f, #d4f2dc);
  --focus: var(--primary);
  --scrim: rgb(22 15 12 / 0.55);

  /* Graph-paper line hierarchy: 1 mm / 5 mm / 10 mm */
  --paper-unit: 8px;
  --grid-fine: color-mix(in srgb, var(--brand) 8%, transparent);
  --grid-mid: color-mix(in srgb, var(--brand) 15%, transparent);
  --grid-bold: color-mix(in srgb, var(--brand) 26%, transparent);

  /* Type scale (fluid, 360 → 1440 px viewport) */
  --fs-display: clamp(2.5rem, 1.5rem + 4.444vw, 5.5rem);
  --fs-h1: clamp(2.125rem, 1.583rem + 2.407vw, 3.75rem);
  --fs-h2: clamp(1.75rem, 1.417rem + 1.481vw, 2.75rem);
  --fs-h3: clamp(1.375rem, 1.25rem + 0.556vw, 1.75rem);
  --fs-body-l: clamp(1.125rem, 1.083rem + 0.185vw, 1.25rem);
  --fs-body: clamp(1rem, 0.958rem + 0.185vw, 1.125rem);
  --fs-label: clamp(0.875rem, 0.854rem + 0.093vw, 0.938rem);
  --fs-eyebrow: clamp(0.75rem, 0.729rem + 0.093vw, 0.812rem);

  /* Spacing: 8 px base */
  --sp-4: 0.25rem;
  --sp-8: 0.5rem;
  --sp-12: 0.75rem;
  --sp-16: 1rem;
  --sp-24: 1.5rem;
  --sp-32: 2rem;
  --sp-48: 3rem;
  --sp-64: 4rem;
  --sp-96: 6rem;
  --sp-128: 8rem;
  --section-y: clamp(4rem, 2rem + 6vw, 8rem);

  /* Layout */
  --margin: clamp(1.25rem, 0.5rem + 3.5vw, 4rem);
  --gutter: clamp(1rem, 0.5rem + 2vw, 2rem);
  --container: 80rem; /* 1280 */
  --container-wide: 100rem; /* 1600: gallery pages */
  --mark-h-top: clamp(6rem, 4rem + 6vw, 9.5rem); /* header logo at the top of the page: 96 → 152 px (collapsed: 44 px) */
  --measure: 65ch;

  /* Shape: square everywhere, pills are the one deliberate exception */
  --radius-0: 0;
  --radius-pill: 999px;

  /* Layers (tonal, no heavy shadows) */
  --z-base: 0;
  --z-raised: 10;
  --z-header: 100;
  --z-overlay: 200;
  --z-intro: 300;

  /* Motion */
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-decel: cubic-bezier(0, 0, 0, 1);
  --ease-emph: cubic-bezier(0.05, 0.7, 0.1, 1);
  --ease-spring: cubic-bezier(0.34, 1.35, 0.64, 1);
  --dur-short: 150ms;
  --dur-medium: 300ms;
  --dur-long: 500ms;
  --dur-xl: 800ms;
}
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --ease-spring: linear(0, 0.069, 0.224, 0.407, 0.583, 0.733, 0.849, 0.933, 0.987, 1.019, 1.034, 1.038, 1.036, 1.03, 1.023, 1.016, 1.01, 1.006, 1.003, 1.001, 0.999, 1);
  }
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* Section themes: self-contained surfaces, identical in light and dark.
   --t-bg background · --t-on text · --t-faded inactive titles (large text only on coral).
   Logo state (data-logo on the header) per theme: terracotta, moss = light · graphite = brand · slate, sage, mustard = ink.
   Coral under the transparent header: not allowed (no state reaches 4.5:1 for the links there). The category pages use the tonal band below instead. */
.theme-terracotta { --t-bg: #682716; --t-on: #f7efeb; --t-faded: #cea194; }
.theme-coral      { --t-bg: #f64c3f; --t-on: #1a0b09; --t-faded: #5a1a14; } /* faded: large titles only (3.8:1) */
.theme-container  { --t-bg: var(--primary-container); --t-on: var(--on-primary-container); --t-faded: var(--on-primary-container); } /* the one theme that follows light/dark: soft peach in light, deep wine in dark */
.theme-graphite   { --t-bg: #2a2522; --t-on: #f7efeb; --t-faded: #b9a8a0; --t-logo: var(--brand); }
.theme-slate      { --t-bg: #90b7bd; --t-on: #002024; --t-faded: #21484d; }
.theme-moss       { --t-bg: #2f3b20; --t-on: #eef3e2; --t-faded: #aebd8f; }
.theme-sage       { --t-bg: #b9cba3; --t-on: #18220d; --t-faded: #3f5329; }
.theme-mustard    { --t-bg: #e3b341; --t-on: #2b1c00; --t-faded: #5f4200; }
.themed {
  background: var(--t-bg);
  color: var(--t-on);
  --focus: var(--t-on);
  --outline: var(--t-on);
  --outline-variant: color-mix(in srgb, var(--t-on) 35%, transparent);
  --on-surface-variant: var(--t-on);
}

/* ---------- 3. Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
  hanging-punctuation: first;
}
body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--on-bg);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.6;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}
img, svg, video, picture { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--primary); text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }
p, ul, ol, figure, blockquote, dl { margin-block: 0; }
:where(h1, h2, h3, h4) { margin-block: 0; }
hr { border: 0; border-top: 1px solid var(--outline-variant); margin-block: var(--sp-32); }
::selection { background: var(--brand); color: var(--on-brand); }
[hidden] { display: none !important; }
html.is-locked, html.intro-pending { overflow: hidden; }
.sr-only {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed; inset-block-start: var(--sp-8); inset-inline-start: var(--sp-8);
  z-index: calc(var(--z-intro) + 1);
  padding: var(--sp-12) var(--sp-24);
  background: var(--on-bg); color: var(--bg);
  border-radius: var(--radius-pill);
  font-weight: 600; text-decoration: none;
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* ---------- 4. Type ---------- */
:where(h1, h2, h3, .display, .h1, .h2, .h3) {
  font-family: var(--font-display);
  font-weight: 400;
  font-synthesis: none;
  text-wrap: balance;
  line-height: 1.08;
  letter-spacing: -0.005em;
}
.display { font-size: var(--fs-display); line-height: 1.02; letter-spacing: -0.012em; }
:where(h1), .h1 { font-size: var(--fs-h1); line-height: 1.05; }
:where(h2), .h2 { font-size: var(--fs-h2); }
:where(h3), .h3 { font-size: var(--fs-h3); line-height: 1.2; }
.body-l { font-size: var(--fs-body-l); line-height: 1.55; }
.label { font-size: var(--fs-label); font-weight: 500; line-height: 1.4; }
.eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
}
.num { font-variant-numeric: tabular-nums lining-nums; font-feature-settings: "tnum", "lnum"; }
.prose { max-width: var(--measure); text-wrap: pretty; hyphens: auto; }
.prose > * + * { margin-block-start: 1em; }
.muted { color: var(--on-surface-variant); }

/* ---------- 5. Layout ---------- */
.container { width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; }
.container--wide { width: min(100% - 2 * var(--margin), var(--container-wide)); }
.container--narrow { width: min(100% - 2 * var(--margin), var(--measure)); }
.full-bleed { width: 100%; }
.section { padding-block: var(--section-y); position: relative; }
.stack > * + * { margin-block-start: var(--stack, var(--sp-16)); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--cluster, var(--sp-12)); align-items: center; }
.grid { display: grid; gap: var(--gutter); grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (min-width: 48em) { .grid { grid-template-columns: repeat(8, minmax(0, 1fr)); } }
@media (min-width: 64em) { .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); } }
.grid > * { grid-column: 1 / -1; }
@media (min-width: 48em) { .md-half { grid-column: span 4; } }
@media (min-width: 64em) {
  .lg-3 { grid-column: span 3; } .lg-4 { grid-column: span 4; } .lg-5 { grid-column: span 5; }
  .lg-6 { grid-column: span 6; } .lg-7 { grid-column: span 7; } .lg-8 { grid-column: span 8; }
  .lg-start-7 { grid-column-start: 7; } .lg-start-9 { grid-column-start: 9; }
}
/* Visible grid overlay for design review (toggle with data-grid on <html>) */
html[data-grid]::after {
  content: ""; position: fixed; inset: 0; z-index: calc(var(--z-intro) + 2); pointer-events: none;
  width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto;
  background: repeating-linear-gradient(90deg, rgb(246 76 63 / 0.14) 0 calc((100% - 3 * var(--gutter)) / 4), transparent 0 calc((100% - 3 * var(--gutter)) / 4 + var(--gutter)));
}
@media (min-width: 48em) { html[data-grid]::after { background: repeating-linear-gradient(90deg, rgb(246 76 63 / 0.14) 0 calc((100% - 7 * var(--gutter)) / 8), transparent 0 calc((100% - 7 * var(--gutter)) / 8 + var(--gutter))); } }
@media (min-width: 64em) { html[data-grid]::after { background: repeating-linear-gradient(90deg, rgb(246 76 63 / 0.14) 0 calc((100% - 11 * var(--gutter)) / 12), transparent 0 calc((100% - 11 * var(--gutter)) / 12 + var(--gutter))); } }

/* ---------- 6. Paper motif (graph paper: fine 1×, mid 5×, bold 10×) ---------- */
.paper {
  --u: var(--paper-unit);
  background-image:
    linear-gradient(var(--grid-bold) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-bold) 1px, transparent 1px),
    linear-gradient(var(--grid-mid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-mid) 1px, transparent 1px),
    linear-gradient(var(--grid-fine) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-fine) 1px, transparent 1px);
  background-size:
    calc(var(--u) * 10) calc(var(--u) * 10), calc(var(--u) * 10) calc(var(--u) * 10),
    calc(var(--u) * 5) calc(var(--u) * 5), calc(var(--u) * 5) calc(var(--u) * 5),
    var(--u) var(--u), var(--u) var(--u);
  background-position: center top;
}
.paper--fade { mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%); }
.paper--fade-both { mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%); }
/* Fine paper behind a content block that must stay readable */
.paper-bg { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.paper-host { position: relative; isolation: isolate; }
.paper-host > :not(.paper-bg) { position: relative; z-index: 1; }
/* Ruler: ticks at 1/5/10 module */
.ruler, .menu__list li::after {
  height: 14px; color: var(--outline);
  background:
    repeating-linear-gradient(90deg, currentColor 0 1px, transparent 1px calc(var(--paper-unit) * 10)) bottom / 100% 14px no-repeat,
    repeating-linear-gradient(90deg, currentColor 0 1px, transparent 1px calc(var(--paper-unit) * 5)) bottom / 100% 9px no-repeat,
    repeating-linear-gradient(90deg, currentColor 0 1px, transparent 1px var(--paper-unit)) bottom / 100% 4px no-repeat;
  border-bottom: 1px solid currentColor;
}
/* Line-weight rules */
.rule { border: 0; border-top: 1px solid var(--outline-variant); margin: 0; }
.rule--mid { border-top-width: 2px; border-top-color: var(--outline); }
.rule--bold { border-top-width: 3px; border-top-color: var(--brand); }
/* Dimension line: ├──── 1250 mm ────┤. Add data-dim: main.js writes the real length of the line as a label,
   at the drawing scale 8 px = 10 mm (one paper unit = 1 cm), and updates it when the window is resized. */
.dim {
  display: flex; align-items: center; gap: var(--sp-12);
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--on-surface-variant); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.dim::before, .dim::after {
  content: ""; flex: 1; height: 9px;
  background: linear-gradient(currentColor, currentColor) center / 100% 1px no-repeat;
}
.dim::before { border-inline-start: 1px solid currentColor; }
.dim::after { border-inline-end: 1px solid currentColor; }
/* Vertical dimension line (give the parent a height; e.g. along a photo) */
.dim--v { flex-direction: column; height: 100%; writing-mode: vertical-rl; }
.dim--v::before, .dim--v::after { height: auto; width: 9px; background: linear-gradient(currentColor, currentColor) center / 1px 100% no-repeat; }
.dim--v::before { border-inline-start: 0; border-block-start: 1px solid currentColor; }
.dim--v::after { border-inline-end: 0; border-block-end: 1px solid currentColor; }
/* Section opener: number + ruler across the top of a section  "01 ▕▏▏▏▏▏▏▏" */
.opener { display: flex; align-items: flex-end; gap: var(--sp-16); color: var(--on-surface-variant); }
.opener .ruler { flex: 1; }
.opener .eyebrow { line-height: 1; }
/* Section head recipe: opener (number + ruler), then heading left and text/button right (stacked on mobile) */
.section-head { display: grid; gap: clamp(2.5rem, 1.75rem + 3vw, 4.5rem); }
.section-head__body { align-items: start; row-gap: var(--sp-32); }
.section-head__body > h2 { text-wrap: balance; }
@media (min-width: 64em) { .section-head__body > .section-head__side { grid-column: 8 / -1; padding-block-start: 0.4em; } }
.section-head__side .btn { margin-block-start: var(--sp-32); }
/* Ruler along the bottom of a hero (on photo: white) */
.hero__ruler { position: absolute; inset: auto 0 0 0; color: rgb(255 255 255 / 0.8); }
.hero__ruler .ruler { color: inherit; width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; }
/* Draw-on: rulers and dimension lines draw themselves in when they scroll into view (main.js adds .is-in).
   Use data-draw-load instead for things already on screen at load (hero ruler): drawn right away, or after the home intro. */
.js [data-draw], .js [data-draw-load] { -webkit-mask: linear-gradient(#000 0 0) left center / 0% 100% no-repeat; mask: linear-gradient(#000 0 0) left center / 0% 100% no-repeat; transition: mask-size var(--dur-xl) var(--ease-emph), -webkit-mask-size var(--dur-xl) var(--ease-emph); }
.js [data-draw].is-in, .js [data-draw-load].is-in { -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }
/* Counter  01 / 10 */
.counter { font-variant-numeric: tabular-nums; font-family: var(--font-display); font-size: var(--fs-h3); line-height: 1; }
.counter small { font-family: var(--font-body); font-size: var(--fs-eyebrow); letter-spacing: 0.14em; opacity: 0.8; }

/* ---------- 7. Buttons (pill) with Material ripple ---------- */
.btn {
  --btn-bg: var(--brand);
  --btn-fg: var(--on-brand);
  --btn-border: transparent;
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-8);
  min-height: 3rem; min-width: 3rem; padding: 0.7rem 1.6rem;
  border: 1px solid var(--btn-border); border-radius: var(--radius-pill);
  background: var(--btn-bg); color: var(--btn-fg);
  font-size: var(--fs-label); font-weight: 600; line-height: 1.2; letter-spacing: 0.005em;
  text-decoration: none; text-align: center; white-space: nowrap;
  -webkit-tap-highlight-color: transparent; user-select: none;
  transition: box-shadow var(--dur-medium) var(--ease-standard), background-color var(--dur-medium) var(--ease-standard);
}
/* M3 state layer: hover 8 %, focus/pressed 10 % */
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1; background: currentColor; opacity: 0;
  transition: opacity var(--dur-short) var(--ease-standard);
}
@media (hover: hover) { .btn:hover::before { opacity: 0.08; } }
.btn:focus-visible::before { opacity: 0.1; }
.btn:active::before { opacity: 0.1; }
.btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.btn--tonal { --btn-bg: var(--primary-container); --btn-fg: var(--on-primary-container); }
.btn--outline { --btn-bg: transparent; --btn-fg: currentColor; --btn-border: var(--outline); }
.btn--text { --btn-bg: transparent; --btn-fg: var(--primary); padding-inline: 1rem; }
.btn--invert { --btn-bg: var(--t-on, var(--on-bg)); --btn-fg: var(--t-bg, var(--bg)); }
.btn--on-photo { --btn-bg: #fff; --btn-fg: #201a18; }
.btn--on-photo-outline { --btn-bg: transparent; --btn-fg: #fff; --btn-border: rgb(255 255 255 / 0.7); }
.btn--arrow::after {
  content: ""; width: 1.25em; height: 1.25em; background: currentColor; flex: none;
  mask: var(--icon-arrow) center / contain no-repeat;
  transition: transform var(--dur-medium) var(--ease-spring);
}
@media (hover: hover) { .btn--arrow:hover::after { transform: translateX(4px); } }
.btn:is(:disabled, [aria-disabled="true"]) { opacity: 0.38; pointer-events: none; }
.btn--icon { padding: 0; width: 3rem; }
/* Ripple (created by main.js at the pointer position) */
.ripple {
  position: absolute; z-index: -1; border-radius: 50%; background: currentColor; opacity: 0.16;
  pointer-events: none; transform: scale(0);
  animation: ripple var(--dur-xl) var(--ease-decel) forwards;
}
@keyframes ripple { 60% { opacity: 0.16; } to { transform: scale(1); opacity: 0; } }
@media (forced-colors: active) { .btn { border-color: ButtonText; } }

/* Icons as masks (no extra requests) */
:root {
  --icon-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5'%3E%3Cpath d='M4 12h16M14 6l6 6-6 6'/%3E%3C/svg%3E");
  --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Cpath d='M5 5l14 14M19 5L5 19'/%3E%3C/svg%3E");
  --icon-prev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Cpath d='M15 4l-8 8 8 8'/%3E%3C/svg%3E");
  --icon-next: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Cpath d='M9 4l8 8-8 8'/%3E%3C/svg%3E");
  --icon-theme: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6'%3E%3Ccircle cx='12' cy='12' r='8'/%3E%3Cpath d='M12 4v16' /%3E%3Cpath d='M12 4a8 8 0 010 16z' fill='%23000'/%3E%3C/svg%3E");
  --icon-alert: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8'%3E%3Cpath d='M12 3l10 18H2z'/%3E%3Cpath d='M12 10v5M12 18v.5'/%3E%3C/svg%3E");
  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Cpath d='M4 12.5l5 5L20 6.5'/%3E%3C/svg%3E");
}
.icon { width: 1.5rem; height: 1.5rem; background: currentColor; flex: none; mask: var(--icon, none) center / contain no-repeat; display: inline-block; }
.icon--close { --icon: var(--icon-close); } .icon--prev { --icon: var(--icon-prev); } .icon--next { --icon: var(--icon-next); }
.icon--theme { --icon: var(--icon-theme); } .icon--alert { --icon: var(--icon-alert); } .icon--check { --icon: var(--icon-check); } .icon--arrow { --icon: var(--icon-arrow); }

/* ---------- 8. Header & menu ---------- */
/* Header states (attributes on <header class="site-header">):
   data-logo  "accent" (default, coral logo on the plain page) · "light" (white, over photos, terracotta, moss) ·
              "brand" (coral logo with light links, over graphite) · "ink" (dark, over slate, sage, mustard):
              what sits behind the header at the top of the page.
   data-solid the bar is solid from the start (pages without a hero). Otherwise it is transparent until scrolled.
   data-scrolled  set by main.js after ~32 px: solid tonal bar, small logo, accent colours.
   html.menu-open  set by main.js while the mobile menu is open: graphite bar, coral logo, light icon. */
.site-header {
  --hdr-fg: var(--on-bg); --logo: var(--brand); --hdr-active: var(--primary); --mark-h: var(--mark-h-top);
  position: fixed; inset: 0 0 auto 0; z-index: var(--z-header);
  color: var(--hdr-fg);
  background-color: transparent;
  transition: background-color var(--dur-long) var(--ease-standard), color var(--dur-medium) var(--ease-standard);
  view-transition-name: site-header;
  --focus: currentColor;
}
.site-header[data-logo="light"] { --hdr-fg: #fff; --logo: #fff; --hdr-active: #ffb4a7; }
.site-header[data-logo="brand"] { --hdr-fg: #f7efeb; --logo: var(--brand); --hdr-active: #ffb4a7; }
.site-header[data-logo="ink"] { --hdr-fg: #201a18; --logo: #201a18; --hdr-active: #7d000e; }
.site-header[data-logo="on-container"] { --hdr-fg: var(--on-primary-container); --logo: var(--on-primary-container); --hdr-active: var(--primary); } /* over the tonal band of the category pages; follows light/dark (links 13:1, current page 4.7:1 light / 9:1 dark) */
.site-header[data-solid], .site-header[data-scrolled] {
  --hdr-fg: var(--on-bg); --logo: var(--brand); --hdr-active: var(--primary); --focus: var(--primary);
  background-color: var(--surface); /* clearly off the page colour, so no border line is needed */
}
.site-header[data-scrolled] { --mark-h: 2.75rem; }
html.menu-open .site-header, html.menu-open .site-header[data-bar] { --hdr-fg: #f7efeb; --logo: var(--brand); --hdr-active: var(--brand); --focus: #fff; background-color: #2a2522; }
.site-header__bar {
  display: flex; align-items: center; gap: var(--sp-16);
  width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto;
  padding-block: var(--sp-16);
  transition: padding var(--dur-long) var(--ease-emph);
}
.site-header[data-scrolled] .site-header__bar { padding-block: var(--sp-8); }
.brand-link {
  display: block; color: var(--logo); line-height: 0; flex: none; min-height: 2.75rem; min-width: 2.75rem;
  transition: color var(--dur-medium) var(--ease-standard);
}
.brand-link .mark {
  height: var(--mark-h); width: auto; aspect-ratio: 381 / 397.23;
  transition: height var(--dur-long) var(--ease-emph); /* header is fixed: this never shifts page content */
}
/* Links sit next to the logo, vertically centred on it; the current page changes colour (no underline) */
.site-nav { display: none; align-items: center; margin-inline-start: var(--sp-32); }
.site-nav ul { display: flex; gap: var(--sp-4); list-style: none; margin: 0; padding: 0; }
.site-nav a {
  display: inline-flex; align-items: center; min-height: 2.75rem; padding-inline: var(--sp-16);
  color: inherit; text-decoration: none; font-size: var(--fs-label); font-weight: 500;
  transition: color var(--dur-medium) var(--ease-standard);
}
.site-nav a:hover, .site-nav a[aria-current="page"], .site-nav a[aria-current="true"] { color: var(--hdr-active); }
/* The current page (or section) in the nav: its colour + a 2 px underline, the same on every page and on every header background */
.site-nav a[aria-current="page"], .site-nav a[aria-current="true"] { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.45em; }
.hdr-tools { display: flex; align-items: center; gap: var(--sp-4); margin-inline-start: auto; }
.lang-toggle { display: inline-flex; align-items: center; font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.12em; }
.hdr-tools .lang-toggle { display: none; }
.lang-toggle a {
  display: inline-grid; place-items: center; min-width: 2.75rem; min-height: 2.75rem;
  color: inherit; text-decoration: none; opacity: 0.72;
}
.lang-toggle a[aria-current="true"] { opacity: 1; text-decoration: underline; text-underline-offset: 0.4em; text-decoration-thickness: 1px; }
.lang-toggle a:hover { opacity: 1; }
.icon-btn {
  position: relative; display: inline-grid; place-items: center; width: 2.75rem; height: 2.75rem;
  background: transparent; border: 0; color: inherit; border-radius: var(--radius-pill); overflow: hidden; isolation: isolate;
}
.icon-btn::before { content: ""; position: absolute; inset: 0; background: currentColor; opacity: 0; z-index: -1; transition: opacity var(--dur-short); }
@media (hover: hover) { .icon-btn:hover::before { opacity: 0.08; } }
.icon-btn:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; }
/* Hamburger: two lines that turn into an X. Icon-only (the label lives in aria-label); the lines line up with the page margin */
.menu-btn { width: 3rem; height: 3rem; margin-inline-end: -0.75rem; }
.burger { position: relative; display: block; width: 1.5rem; height: 1.5rem; }
.burger i {
  position: absolute; inset-inline: 0; top: 50%; height: 2px; margin-block-start: -1px; background: currentColor;
  transition: transform var(--dur-long) var(--ease-emph);
}
.burger i:first-child { transform: translateY(-4px); }
.burger i:last-child { transform: translateY(4px); }
.menu-btn[aria-expanded="true"] .burger i:first-child { transform: rotate(45deg); }
.menu-btn[aria-expanded="true"] .burger i:last-child { transform: rotate(-45deg); }
@media (min-width: 48em) {
  .site-nav { display: flex; }
  .menu-btn { display: none; }
  .hdr-tools .lang-toggle { display: inline-flex; }
}
/* Mobile menu: a panel UNDER the header (the header, logo and X never move). Rises from the bottom like the page transitions.
   Add class "themed theme-graphite" to the element. Not a <dialog>: main.js makes the page inert while it is open. */
.menu {
  position: fixed; inset: 0; z-index: calc(var(--z-header) - 1); overflow: auto; --focus: #fff;
  visibility: hidden; clip-path: inset(100% 0 0 0);
  transition: clip-path var(--dur-long) var(--ease-emph), visibility 0s linear var(--dur-long);
}
.menu[data-open] { visibility: visible; clip-path: inset(0); transition: clip-path var(--dur-long) var(--ease-emph), visibility 0s; }
.menu__inner {
  width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; min-height: 100dvh;
  display: grid; grid-template-rows: 1fr auto; padding-block: calc(var(--mark-h-top) + var(--sp-32)) var(--sp-32);
}
.menu__list { list-style: none; margin: 0; padding: 0; align-self: center; counter-reset: m; }
.menu__list li { counter-increment: m; }
.menu__list li::after { content: ""; display: block; color: color-mix(in srgb, var(--t-on) 55%, transparent); clip-path: inset(0 100% 0 0); transition: clip-path var(--dur-long) var(--ease-emph); }
.menu[data-open] .menu__list li::after { clip-path: inset(0); transition-delay: calc(var(--i) * 70ms + 260ms); }
.menu__list a {
  display: flex; align-items: baseline; gap: var(--sp-16); padding-block: var(--sp-16) var(--sp-12);
  font-family: var(--font-display); font-size: var(--fs-h1); line-height: 1.1; color: inherit; text-decoration: none;
  opacity: 0; transform: translateY(1.5rem);
  transition: opacity var(--dur-long) var(--ease-emph), transform var(--dur-long) var(--ease-emph), color var(--dur-medium) var(--ease-standard);
}
.menu[data-open] .menu__list a { opacity: 1; transform: none; transition-delay: calc(var(--i) * 70ms + 180ms), calc(var(--i) * 70ms + 180ms), 0s; }
.menu__list a::before { content: "0" counter(m); font-family: var(--font-body); font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.14em; opacity: 0.7; }
.menu__list a[aria-current="page"], .menu__list a[aria-current="true"], .menu__list a:hover { color: var(--brand); }
.menu__foot { padding-block-start: var(--sp-24); display: flex; align-items: center; }
.menu__foot .lang-toggle { margin-inline-start: -0.75rem; }
/* Space for the fixed header on pages without a hero */
.page-top { padding-block-start: calc(var(--mark-h-top) + var(--sp-32) + var(--sp-64)); }

/* ---------- 9. Hero & themed sections ---------- */
.hero { position: relative; isolation: isolate; min-height: 100vh; min-height: 100dvh; display: grid; align-items: end; color: #fff; --focus: #fff; overflow: clip; }
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media > img, .hero__media > .frame { width: 100%; height: 100%; object-fit: cover; }
.hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(to bottom, rgb(22 15 12 / 0.55), rgb(22 15 12 / 0.35) 40%, rgb(22 15 12 / 0.6)); }
.hero__inner { width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; padding-block: clamp(6rem, 4rem + 6vw, 8rem) var(--sp-48); }
.hero__title { max-width: 14ch; }
.on-photo { color: #fff; --focus: #fff; }
/* Hero recipe: .hero (full screen, home) · .hero--compact (inner pages) · .hero__ruler along the bottom edge */
.hero--compact { min-height: min(72vh, 44rem); min-height: min(72dvh, 44rem); }
.hero__inner > .eyebrow { opacity: 0.9; }
.hero__actions { margin-block-start: clamp(2rem, 1.5rem + 2vw, 3.5rem); }
.hero__inner { padding-block-end: calc(var(--sp-48) + 14px); }

/* ---------- 10. Categories (faded / active list; carousel on mobile) ---------- */
.cats { position: relative; transition: background-color var(--dur-long) var(--ease-standard), color var(--dur-long) var(--ease-standard); }
.cats__inner { display: grid; gap: var(--gutter); }
.cats__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.cats__link {
  display: flex; align-items: baseline; gap: var(--sp-16); padding-block: var(--sp-8); min-height: 2.75rem;
  font-family: var(--font-display); font-size: clamp(1.375rem, 1rem + 1.2vw, 2rem); line-height: 1.15; text-decoration: none;
  color: var(--t-faded); transition: color var(--dur-medium) var(--ease-standard);
}
.cats__link .eyebrow { font-family: var(--font-body); min-width: 2.5ch; }
.cats__link[aria-current="true"], .cats__link:focus-visible { color: var(--t-on); }
.cats__link:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }
.cats__media { position: relative; }
.cats__panel { display: none; }
.cats__panel[data-active] { display: block; animation: rise-in var(--dur-xl) var(--ease-emph) both; }
.cats__text { max-width: 44ch; }
.cats__text .btn { margin-block-start: var(--sp-24); white-space: normal; }
@media (min-width: 64em) {
  .cats__inner { grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: center; min-height: 0; }
  .cats__head { grid-column: 1 / span 5; }
  .cats__media { grid-column: 6 / span 4; }
  .cats__side { grid-column: 10 / -1; }
}
/* Category recipe: desktop = themed section with list/image/text (.cats--desktop, from 64em); phones = swipe carousel (.cats-mobile) */
.cats--desktop { display: none; }
@media (min-width: 64em) { .cats--desktop { display: block; } .cats-mobile { display: none; } }
.cats__top { padding-block-start: var(--sp-96); }
.cats__inner { padding-block: var(--sp-48) var(--sp-96); }
/* Phones: ONE full-screen themed surface with a swipeable strip of slides; the next slide always peeks in.
   Background and text colour change only while swiping (main.js sets the theme class on the section from the slide in view);
   the fixed header takes a tone of the same colour while this section is under it (data-bar, theme class set by main.js). */
.cats-mobile {
  min-height: 100vh; min-height: 100svh; display: flex; flex-direction: column;
  padding-block: calc(3.75rem + var(--sp-24)) var(--sp-32);
  transition: background-color 600ms var(--ease-standard), color 600ms var(--ease-standard);
}
.cats-mobile__top { display: grid; gap: var(--sp-16); width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; }
.cats-mobile .opener { position: relative; }
.opener[data-progress] .ruler::after { content: ""; position: absolute; inset-block-end: 0; inset-inline-start: calc(var(--p, 0) * (100% - 3px)); width: 3px; height: 24px; background: currentColor; }
.opener[data-progress] .ruler { position: relative; }
.cats-carousel { flex: 1; display: flex; gap: var(--sp-16); padding-inline: var(--margin); scroll-padding-inline: var(--margin); min-height: 0; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; margin-block-start: var(--sp-24); }
.cats-carousel::-webkit-scrollbar { display: none; }
.cats-carousel > * { flex: 0 0 calc(100% - var(--margin) - var(--sp-16) - 1.5rem); scroll-snap-align: start; scroll-snap-stop: always; } /* the next slide always peeks in (1.5rem) */
.cat-card { display: grid; grid-template-rows: auto minmax(10rem, 1fr) auto auto; gap: var(--sp-16); }
.cat-card > :is(h2, h3) { min-height: 2.4em; } /* two lines reserved so every slide's image starts at the same height */
.cat-card .frame { aspect-ratio: auto; height: 100%; width: 100%; }
.cat-card .btn { justify-self: start; white-space: normal; }
.site-header[data-bar], .site-header[data-bar][data-scrolled] {
  --hdr-fg: var(--t-on); --logo: var(--t-logo, var(--t-on)); --hdr-active: var(--t-on); --focus: var(--t-on);
  background-color: var(--t-bar);
}
/* in a section colour the links follow the section titles: the current page in the full text colour, the others faded */
.site-header[data-bar] .site-nav a { color: var(--t-faded); }
.site-header[data-bar] .site-nav a:hover, .site-header[data-bar] .site-nav a[aria-current="page"], .site-header[data-bar] .site-nav a[aria-current="true"] { color: var(--t-on); }
.themed, .site-header[data-bar] { --t-bar: color-mix(in srgb, var(--t-on) 10%, var(--t-bg)); }
@media (min-width: 64em) { .cats-mobile { display: none; } }

/* ---------- 11. Gallery & lightbox ---------- */
.gallery { list-style: none; margin-inline: 0; padding: 0; display: grid; gap: var(--sp-8); grid-template-columns: 1fr; }
@media (min-width: 40em) { .gallery { grid-template-columns: repeat(2, 1fr); gap: var(--sp-12); } }
@media (min-width: 48em) { .gallery { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 64em) { .gallery { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 80em) { .gallery { grid-template-columns: repeat(5, 1fr); gap: var(--sp-16); } }
.frame { position: relative; display: block; aspect-ratio: var(--ar, 4 / 5); overflow: hidden; background-color: var(--surface-high); border-radius: var(--radius-0); }
.frame > img { width: 100%; height: 100%; object-fit: cover; transition: transform 1100ms var(--ease-emph); will-change: transform; }
@media (hover: hover) { a.frame:hover > img, button.frame:hover > img { transform: scale(1.08); } }
a.frame, button.frame { padding: 0; border: 0; width: 100%; color: inherit; text-decoration: none; }
a.frame:focus-visible, button.frame:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
/* Placeholder frame (no photo yet): paper + crosshair + proportion label */
.frame--ph { background-color: var(--surface-low); color: var(--on-surface-variant); display: grid; place-items: center; }
.frame--ph::before { content: ""; position: absolute; inset: 0; background: linear-gradient(135deg, transparent calc(50% - 0.5px), var(--outline-variant) 0 calc(50% + 0.5px), transparent 0), linear-gradient(45deg, transparent calc(50% - 0.5px), var(--outline-variant) 0 calc(50% + 0.5px), transparent 0); opacity: 0.7; }
.frame--ph::after { content: attr(data-ph); position: relative; padding: 0.15rem 0.6rem; background: var(--bg); font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.14em; font-variant-numeric: tabular-nums; }
.frame--ph.paper { background-size: 80px 80px, 80px 80px, 40px 40px, 40px 40px, 8px 8px, 8px 8px; }
.themed .frame--ph { background-color: color-mix(in srgb, var(--t-on) 9%, var(--t-bg)); color: var(--t-on); }
.themed .frame--ph::after { background: var(--t-bg); }
.ar-1-1 { --ar: 1 / 1; } .ar-4-5 { --ar: 4 / 5; } .ar-3-2 { --ar: 3 / 2; } .ar-16-9 { --ar: 16 / 9; } .ar-3-4 { --ar: 3 / 4; }
/* Placeholder frames: the paper grid zooms on hover, like a real photo would */
.frame--ph.paper { transition: background-size 1100ms var(--ease-emph); }
@media (hover: hover) { a.frame--ph.paper:hover, button.frame--ph.paper:hover { background-size: 160px 160px, 160px 160px, 80px 80px, 80px 80px, 16px 16px, 16px 16px; } }
/* Gallery load-in (data-tiles on the list, data-tile on each li): tiles glide in from the lower right, fading in, row by row (main.js sets the delay) */
.js [data-tile] > .frame { opacity: 0; transform: translate3d(5vw, 12vh, 0); transition: opacity 900ms var(--ease-standard) var(--td, 0ms), transform 1200ms var(--ease-emph) var(--td, 0ms); }
.js [data-tile].is-in > .frame { opacity: 1; transform: none; }
/* Lightbox */
.lightbox {
  position: fixed; inset: 0; width: 100%; max-width: none; height: 100dvh; max-height: none; margin: 0; padding: 0; border: 0;
  background: rgb(22 15 12 / 0.95); color: #f7efeb; z-index: var(--z-overlay); --focus: #fff;
}
.lightbox::backdrop { background: rgb(22 15 12 / 0.95); }
.lightbox[open] { display: grid; grid-template-rows: auto 1fr auto; }
html:not(.vt-lightbox) .lightbox[open] { animation: fade-in var(--dur-medium) var(--ease-standard); }
.lightbox.is-closing { animation: fade-out 250ms var(--ease-standard) both; }
.lightbox__bar { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-16) var(--margin); }
.lightbox__stage { position: relative; display: flex; overflow-x: auto; overflow-y: hidden; min-height: 0; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior: contain; touch-action: pan-x; }
.lightbox__stage::-webkit-scrollbar { display: none; }
.lightbox__slide { flex: 0 0 100%; scroll-snap-align: center; scroll-snap-stop: always; margin: 0; padding-inline: var(--margin); display: grid; place-items: center; min-height: 0; }
.lightbox__slide img { max-height: calc(100dvh - 12rem); width: auto; max-width: 100%; height: auto; }
.lightbox__slide .frame { height: calc(100dvh - 12rem); width: auto; max-width: 90vw; }
.lightbox__caption { padding: var(--sp-16) var(--margin) var(--sp-24); text-align: center; font-size: var(--fs-label); }
.lightbox .icon-btn { background: rgb(255 255 255 / 0.1); }
.lightbox__nav { position: absolute; inset-block: 0; display: grid; align-items: center; padding-inline: var(--sp-8); }
.lightbox__nav--prev { inset-inline-start: 0; } .lightbox__nav--next { inset-inline-end: 0; }
@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }
.lightbox__nav .icon-btn[aria-disabled="true"] { opacity: 0.3; pointer-events: none; }

/* ---------- 12. Forms ---------- */
.field { display: grid; gap: var(--sp-8); }
.field > label, .field > .label-text { font-size: var(--fs-label); font-weight: 600; }
.field .hint { font-size: var(--fs-label); color: var(--on-surface-variant); }
.input, .textarea, .select {
  width: 100%; min-height: 3rem; padding: 0.7rem 1rem; font-size: 1rem; /* ≥16px: no iOS zoom */
  background: var(--surface-lowest); color: var(--on-surface);
  border: 1px solid var(--outline); border-radius: var(--radius-0);
  box-shadow: inset 0 0 0 0 var(--primary);
  transition: box-shadow var(--dur-short) var(--ease-standard), border-color var(--dur-short);
}
.textarea { min-height: 9rem; resize: vertical; }
.select { appearance: none; padding-inline-end: 3rem; background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-position: calc(100% - 1.5rem) 55%, calc(100% - 1.15rem) 55%; background-size: 0.35rem 0.35rem; background-repeat: no-repeat; }
.input:hover, .textarea:hover, .select:hover { border-color: var(--on-surface); }
.input:focus-visible, .textarea:focus-visible, .select:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary); }
.field[data-invalid] .input, .field[data-invalid] .textarea, .field[data-invalid] .select, .input[aria-invalid="true"] { border-color: var(--error); box-shadow: inset 0 0 0 1px var(--error); }
.field-msg { display: flex; align-items: flex-start; gap: var(--sp-8); font-size: var(--fs-label); font-weight: 500; }
.field-msg--error { color: var(--error); }
.field-msg .icon { width: 1.25rem; height: 1.25rem; margin-block-start: 0.1rem; }
.check { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-12); align-items: start; min-height: 2.75rem; }
.check input { appearance: none; width: 1.5rem; height: 1.5rem; margin: 0.1rem 0 0; border: 1.5px solid var(--outline); background: var(--surface-lowest); display: grid; place-items: center; border-radius: 0; cursor: pointer; flex: none; }
.check input::after { content: ""; width: 1rem; height: 1rem; background: var(--on-primary); mask: var(--icon-check) center / contain no-repeat; transform: scale(0); transition: transform var(--dur-short) var(--ease-spring); }
.check input:checked { background: var(--primary); border-color: var(--primary); }
.check input:checked::after { transform: scale(1); }
.check input:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.check label { font-size: var(--fs-label); }
.form-status { display: flex; gap: var(--sp-12); padding: var(--sp-16) var(--sp-24); border-inline-start: 4px solid currentColor; font-weight: 500; }
.form-status--success { background: var(--success-container); color: var(--on-success-container); border-color: var(--success); }
.form-status--error { background: var(--error-container); color: var(--on-error-container); border-color: var(--error); }
.turnstile-slot { min-height: 65px; display: grid; place-items: center; border: 1px dashed var(--outline); color: var(--on-surface-variant); font-size: var(--fs-eyebrow); letter-spacing: 0.12em; text-transform: uppercase; }

/* ---------- 13. Footer ---------- */
/* Ruler hangs from the top edge, paper grid fades up from the bottom, a dimension line (real width, drawn on) closes the content.
   Markup: see wip/preview/07-footer.html. Real data only: address, phone, email, legal links. */
.site-footer { position: relative; isolation: isolate; background: var(--surface-low); padding-block: var(--sp-48) var(--sp-24); overflow: clip; }
.site-footer > .site-footer__ruler { position: absolute; inset: 0 0 auto 0; color: var(--brand); }
.site-footer__ruler .ruler { transform: scaleY(-1); color: inherit; width: 100%; }
.site-footer > .container { display: flex; flex-direction: column; } /* flex: margins do not collapse, so the snap offset on .dim is exact */
.site-footer .paper-bg { background-position: left top; } /* same origin as the ruler, so its 10 mm ticks sit on the bold paper lines */
.site-footer__grid { display: grid; gap: var(--sp-32) var(--gutter); margin-block: var(--sp-24) var(--sp-24); }
@media (min-width: 48em) { .site-footer__grid { grid-template-columns: repeat(3, 1fr); } }
.site-footer h2 { font-family: var(--font-body); font-size: var(--fs-eyebrow); letter-spacing: 0.16em; text-transform: uppercase; font-weight: 600; color: var(--on-surface-variant); margin-block-end: var(--sp-12); }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer__grid a { color: var(--on-bg); display: inline-block; padding-block: 0.6rem; text-underline-offset: 0.25em; }
@media (hover: hover) { .site-footer__grid a:hover { color: var(--primary); } }
.site-footer address { font-style: normal; }
.site-footer__grid .site-footer__contact a { display: block; width: fit-content; }
/* "Configurar cookies" is an action, so it is a <button> that looks like the footer links */
.site-footer__grid .link-btn { display: inline-block; background: none; border: 0; padding: 0.6rem 0; color: var(--on-bg); font: inherit; text-align: start; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.25em; }
@media (hover: hover) { .site-footer__grid .link-btn:hover { color: var(--primary); text-decoration-thickness: 2px; } }
.site-footer .dim { margin-block-end: var(--sp-16); }
.site-footer__legal { display: flex; flex-wrap: wrap; gap: var(--sp-8) var(--sp-24); justify-content: space-between; align-items: center; font-size: var(--fs-label); color: var(--on-surface-variant); }
.site-footer__legal .lang-toggle { margin-inline-end: -0.75rem; }

/* ---------- 13b. Closing CTA band ---------- */
/* Last block before the footer. Themed, a ruler hangs from its top edge (draws on), big display line + one button.
   Markup: see wip/preview/08-cta-band.html. Text is the owner's. Use one theme per page; never the same as the section above it. */
.cta-band { position: relative; padding-block: clamp(5rem, 3rem + 7vw, 9rem); overflow: clip; }
.cta-band > .cta-band__ruler { position: absolute; inset: 0 0 auto 0; color: var(--t-faded); }
.cta-band__ruler .ruler { transform: scaleY(-1); color: inherit; width: 100%; }
.cta-band__inner { display: grid; gap: var(--sp-48); align-items: end; }
.cta-band__title { font-family: var(--font-display); font-size: var(--fs-display); line-height: 1.02; text-wrap: balance; }
@media (min-width: 64em) {
  .cta-band__inner { grid-template-columns: repeat(12, 1fr); column-gap: var(--gutter); }
  .cta-band__title { grid-column: 1 / 9; }
  .cta-band__action { grid-column: 9 / -1; justify-self: end; }
}

/* ---------- 13c. Next-category navigation ---------- */
/* End of every gallery category page: the whole band is ONE link to the next category, themed with that category's colour
   (last category wraps to the first). Markup: see wip/preview/10-next-category.html. */
.next-cat { position: relative; display: block; color: var(--t-on); text-decoration: none; padding-block: clamp(4rem, 2.5rem + 6vw, 8rem); overflow: clip; }
.next-cat > .cta-band__ruler { position: absolute; inset: 0 0 auto 0; color: var(--t-faded); }
.next-cat__inner { display: grid; gap: var(--sp-32); align-items: end; }
.next-cat__text { display: grid; gap: var(--sp-16); }
.next-cat__title { display: flex; align-items: center; gap: var(--sp-24); font-family: var(--font-display); font-size: var(--fs-h1); line-height: 1.1; font-weight: 400; text-wrap: balance; }
.next-cat__title .icon { width: 0.7em; height: 0.7em; flex: none; transition: transform var(--dur-long) var(--ease-emph); }
.next-cat__icon { display: grid; place-items: center; width: clamp(6rem, 4rem + 8vw, 10rem); aspect-ratio: 1; color: var(--t-on); } /* category icon (inline SVG, currentColor) */
.next-cat__icon svg { width: 100%; height: 100%; }
.next-cat__icon--ph { border: 1px dashed currentColor; font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; opacity: 0.7; }
.next-cat__icon { transition: transform var(--dur-long) var(--ease-emph); }
@media (hover: hover) {
  .next-cat:hover .next-cat__title .icon { transform: translateX(0.25em); }
  .next-cat:hover .next-cat__icon { transform: scale(1.08) rotate(-3deg); }
}
.next-cat:focus-visible { outline: 3px solid var(--t-on); outline-offset: -8px; }
@media (min-width: 64em) {
  .next-cat__inner { grid-template-columns: repeat(12, 1fr); column-gap: var(--gutter); }
  .next-cat__text { grid-column: 1 / 8; align-content: end; }
  .next-cat__icon { grid-column: 12 / -1; justify-self: end; }
}

/* ---------- 13d. Cookie consent banner ---------- */
/* Non-modal dialog fixed bottom-left (full width on phones), always graphite so it reads on any page. Accept and Reject are the same
   style and size (equal prominence); no settings layer (one purpose: analytics). Hidden until main.js decides to show it (no stored choice). Markup: wip/preview/11-cookies.html */
.consent {
  position: fixed; z-index: var(--z-overlay); inset-block-end: var(--sp-16);
  inset-inline-start: max(var(--margin), calc((100vw - var(--container)) / 2));
  width: min(31rem, 100% - 2 * var(--margin)); padding: var(--sp-32) var(--sp-24) var(--sp-24);
  background: var(--t-bg); color: var(--t-on); --focus: var(--t-on);
  display: grid; gap: var(--sp-16); outline: 1px solid color-mix(in srgb, var(--t-on) 24%, transparent); outline-offset: -1px;
  opacity: 0; transform: translateY(1.5rem); visibility: hidden;
  transition: opacity var(--dur-medium) var(--ease-standard), transform var(--dur-long) var(--ease-emph), visibility 0s linear var(--dur-long);
}
.consent[hidden] { display: none; }
.consent[data-open] { opacity: 1; transform: none; visibility: visible; transition-delay: 0s; }
.consent__ruler { position: absolute; inset: 0 0 auto 0; color: var(--t-faded); }
.consent__ruler .ruler { transform: scaleY(-1); color: inherit; }
.consent h2 { font-size: var(--fs-eyebrow); letter-spacing: 0.16em; text-transform: uppercase; font-weight: 600; color: var(--t-faded); }
.consent__text { font-size: var(--fs-label); line-height: 1.5; margin: 0; }
.consent__text a { color: inherit; text-underline-offset: 0.25em; }
.consent__actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); }
.consent__actions .btn { width: 100%; }
@media (prefers-reduced-motion: reduce) { .consent { transform: none; transition-duration: 0.01ms; } }

/* ---------- 14. Motion ---------- */
@keyframes rise-in { from { opacity: 0; transform: translateY(1.5rem); } to { opacity: 1; transform: none; } }
/* Reveal on scroll (only hidden when JS is running). Use data-reveal-load instead for anything already on screen at load
   (hero text and buttons): revealed right away, or after the home intro. data-reveal near the bottom edge of a tall screen never triggers. */
.js [data-reveal], .js [data-reveal-load] { opacity: 0; transform: translateY(1.5rem); transition: opacity var(--dur-xl) var(--ease-emph), transform var(--dur-xl) var(--ease-emph); transition-delay: calc(var(--d, 0) * 80ms); }
.js [data-reveal].is-in, .js [data-reveal-load].is-in { opacity: 1; transform: none; }
/* Intro: graphite screen, coral logo, stripes rise, then the page is revealed from the bottom */
.intro { display: none; }
.intro-pending .intro { display: grid; place-items: center; position: fixed; inset: 0; z-index: var(--z-intro); background: #2a2522; color: var(--brand); animation: intro-out 800ms var(--ease-emph) 1.55s forwards; }
.intro .mark { height: clamp(7rem, 5rem + 10vw, 12rem); width: auto; }
.intro .mark rect { transform-box: fill-box; transform-origin: bottom; animation: stripe-up 700ms var(--ease-emph) backwards; animation-delay: calc(var(--i) * 22ms + 150ms); }
@keyframes stripe-up { from { transform: scaleY(0); opacity: 0; } }
@keyframes intro-out { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(0 0 100% 0); visibility: hidden; } }
/* Page transitions: old page dims and drifts up, new page rises from the bottom; header stays fixed */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  ::view-transition-group(root) { animation-duration: var(--dur-xl); animation-timing-function: var(--ease-emph); }
  ::view-transition-old(root) { animation: vt-out var(--dur-xl) var(--ease-emph) both; z-index: 1; }
  ::view-transition-new(root) { animation: vt-in var(--dur-xl) var(--ease-emph) both; z-index: 2; }
  ::view-transition-group(site-header) { z-index: 10; animation-duration: var(--dur-long); animation-timing-function: var(--ease-emph); }
  ::view-transition-old(site-header), ::view-transition-new(site-header) { animation-duration: var(--dur-medium); }
}
@media (prefers-reduced-motion: no-preference) {
  /* Lightbox open/close: the photo travels between thumbnail and lightbox; the page behind just cross-fades (not the page-transition rise) */
  html.vt-lightbox .site-header { view-transition-name: none; }
  html.vt-lightbox::view-transition-old(root) { animation: none; }
  html.vt-lightbox::view-transition-new(root) { animation: vt-fade-in 500ms var(--ease-standard) both; clip-path: none; }
  ::view-transition-group(lb-img) { animation-duration: 750ms; animation-timing-function: var(--ease-emph); z-index: 5; }
  ::view-transition-old(lb-img), ::view-transition-new(lb-img) { height: 100%; width: 100%; object-fit: cover; overflow: clip; }
}
@keyframes vt-fade-in { from { opacity: 0; } }
@keyframes vt-out { to { filter: brightness(0.35); transform: translateY(-6%); } }
@keyframes vt-in { from { clip-path: inset(100% 0 0 0); transform: translateY(6%); } to { clip-path: inset(0); transform: none; } }

/* ---------- 15. Accessibility & user preferences ---------- */
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
:focus:not(:focus-visible) { outline: none; }
@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; }
  .js [data-reveal], .js [data-reveal-load] { opacity: 1; transform: none; }
  .js [data-draw], .js [data-draw-load] { -webkit-mask: none; mask: none; }
  .intro-pending .intro { display: none; }
  .menu__list a, .menu__list li::after { transition-delay: 0s !important; }
  .js [data-tile] > .frame { opacity: 1; transform: none; }
  .ripple { transform: scale(1); animation: ripple-flash 200ms linear forwards; }
}
@keyframes ripple-flash { from { opacity: 0.16; } to { opacity: 0; } }
@media (forced-colors: active) {
  .input, .textarea, .select, .check input { border-color: CanvasText; }
  .site-header[data-scrolled], .site-header[data-solid] { border-block-end: 1px solid CanvasText; }
}
@media print { .site-header, .intro, .skip-link { display: none !important; } }

/* ---------- 16. Home hero (Phase 3) ----------
   Mockup layout: title + one button in the left/middle, three words stacked bottom right.
   Use on the home page only: <section class="hero hero--home"> with .hero__inner > .hero__main + ul.hero__tags */
.hero__media picture { display: block; width: 100%; height: 100%; }
.hero--home .hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 60% 50%; }
.hero--home .hero__inner {
  display: grid; grid-template-rows: 1fr auto; align-content: stretch; min-height: 100dvh;
  padding-block-start: calc(var(--mark-h-top) + var(--sp-48));
}
.hero--home .hero__main { align-self: center; padding-block-end: var(--sp-32); }
.hero--home .hero__title { max-width: none; font-size: min(var(--fs-display), 9.4vw); } /* keeps "Ebenisteria Rosado." on one line down to 320 px */
.hero--home .hero__title span { display: block; }
.hero__tags {
  justify-self: end; margin: 0; padding: 0; list-style: none; text-align: end;
  font-size: var(--fs-body-l); font-weight: 500; line-height: 1.5; letter-spacing: 0.01em;
}
/* Home hero only: the ruler runs down the right edge, from where the logo ends to the bottom of the hero.
   Ticks point inward (left), drawn top to bottom. */
.hero--home .hero__inner { padding-block-end: var(--sp-48); }
.hero--home .hero__ruler { inset: calc(var(--sp-16) + var(--mark-h-top)) 0 0 auto; width: 14px; }
.hero--home .hero__ruler .ruler {
  width: 100%; height: 100%; margin: 0; border-bottom: 0; border-inline-end: 1px solid currentColor;
  background:
    repeating-linear-gradient(180deg, currentColor 0 1px, transparent 1px calc(var(--paper-unit) * 10)) right / 14px 100% no-repeat,
    repeating-linear-gradient(180deg, currentColor 0 1px, transparent 1px calc(var(--paper-unit) * 5)) right / 9px 100% no-repeat,
    repeating-linear-gradient(180deg, currentColor 0 1px, transparent 1px var(--paper-unit)) right / 4px 100% no-repeat;
}
.js .hero--home .hero__ruler[data-draw-load] { -webkit-mask: linear-gradient(#000 0 0) center top / 100% 0% no-repeat; mask: linear-gradient(#000 0 0) center top / 100% 0% no-repeat; transition: mask-size var(--dur-xl) var(--ease-emph), -webkit-mask-size var(--dur-xl) var(--ease-emph); }
.js .hero--home .hero__ruler[data-draw-load].is-in { -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }

/* ---------- 17. Furniture icons (home, "Fem tota mena de mobles a mida") ----------
   Square frame with the graph-paper grid; one link per furniture category sits on top (inline SVG, currentColor).
   The frame follows the section colour: sheet = section colour with 8 % of the text colour, grid and icons in the text colour.
   Mouse: icons near the pointer lift and grow (dock-style), the nearest one shows its name on an inverted tile.
   Touch: icons stay put, a slow highlight cycles through them; a tap opens the category.
   Markup: .furn[data-furn][data-reveal] > .furn__frame.paper > ul.furn__list > li.furn__item[style="--x;--y;--x5;--y5;--x4;--y4;--i"] > a.furn__link[aria-label] > .furn__ico > svg, + span.furn__name
   Count by frame width (container query): desktop square frame 7 icons from 20rem, 5 from 15rem, 4 below; phone 4:3 frame 7 from 18rem, 5 from 14rem, 4 below. */
.furn { container: furn / inline-size; width: min(100%, 34rem); }
.furn__frame {
  --fg: var(--t-on, var(--on-bg)); --sheet: var(--t-bg, var(--bg));
  /* same graph paper as the footer: fine every 8 px, mid every 40 px, bold every 80 px, drawn from the top-left corner so the sequence starts cleanly
     (the first line is tucked under the frame border); the three weights are spaced wider apart so the bold/mid/fine rhythm reads on the dark sheet */
  --grid-fine: color-mix(in srgb, var(--fg) 7%, transparent);
  --grid-mid: color-mix(in srgb, var(--fg) 16%, transparent);
  --grid-bold: color-mix(in srgb, var(--fg) 24%, transparent);
  background-position: -1px -1px;
  position: relative; aspect-ratio: 1; border-radius: var(--radius-0);
  background-color: color-mix(in srgb, var(--fg) 8%, var(--sheet));
  border: 1px solid color-mix(in srgb, var(--fg) 45%, transparent);
  transition: background-color 600ms var(--ease-standard), border-color 600ms var(--ease-standard);
}
.furn__list { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; }
.furn__item {
  --sz: 22%; --p: 0;
  position: absolute; left: calc(var(--x) * 1%); top: calc(var(--y) * 1%);
  width: var(--sz); aspect-ratio: 1; translate: -50% -50%;
}
/* Positions (% of the frame). Portrait (desktop, square frame): 2+3+2 / 2+3 / 2x2. Landscape (phones, 4:3 frame): 4+3 / 3+2 / 2x2. */
.furn__item:nth-child(1) { --x:36;--y:22;--lx:14;--ly:30;--x5:36;--y5:32;--lx5:22;--ly5:30;--x4:30;--y4:30;--lx4:30;--ly4:30; }
.furn__item:nth-child(2) { --x:64;--y:22;--lx:38;--ly:30;--x5:64;--y5:32;--lx5:50;--ly5:30;--x4:70;--y4:30;--lx4:70;--ly4:30; }
.furn__item:nth-child(3) { --x:22;--y:50;--lx:62;--ly:30;--x5:22;--y5:68;--lx5:78;--ly5:30;--x4:30;--y4:70;--lx4:30;--ly4:70; }
.furn__item:nth-child(4) { --x:50;--y:50;--lx:86;--ly:30;--x5:50;--y5:68;--lx5:36;--ly5:70;--x4:70;--y4:70;--lx4:70;--ly4:70; }
.furn__item:nth-child(5) { --x:78;--y:50;--lx:26;--ly:70;--x5:78;--y5:68;--lx5:64;--ly5:70; }
.furn__item:nth-child(6) { --x:36;--y:78;--lx:50;--ly:70; }
.furn__item:nth-child(7) { --x:64;--y:78;--lx:74;--ly:70; }
.furn__item[data-hot] { z-index: 2; }
.furn__link {
  position: absolute; inset: 0; display: grid; place-items: center; color: var(--fg); text-decoration: none;
  transform: translateY(calc(var(--p) * -7%)) scale(calc(1 + var(--p) * 0.42));
  transition: transform var(--dur-medium) var(--ease-emph), color var(--dur-short) var(--ease-standard);
  -webkit-tap-highlight-color: transparent;
}
.furn__link::before { /* tile that appears under the lifted icon; the icon turns to the sheet colour */
  content: ""; position: absolute; inset: 6%; background: var(--fg);
  opacity: 0; transform: scale(0.85); transition: opacity var(--dur-short) var(--ease-standard), transform var(--dur-medium) var(--ease-emph);
}
.furn__item[data-hot] .furn__link { color: var(--sheet); }
.furn__item[data-hot] .furn__link::before { opacity: 1; transform: none; }
.furn__link:focus-visible { outline: 3px solid var(--focus); outline-offset: 6px; }
.furn__ico { position: relative; display: grid; place-items: center; width: 100%; height: 100%; }
.furn__ico svg { width: 62%; height: 62%; fill: currentColor; }
.furn__name {
  position: absolute; left: 50%; bottom: calc(100% + 34%); z-index: 3; width: max-content; max-width: 10rem;
  padding: 0.35rem 0.7rem; background: var(--fg); color: var(--sheet); text-align: center; text-wrap: balance;
  font-size: var(--fs-label); font-weight: 600; line-height: 1.25; pointer-events: none;
  opacity: 0; transform: translate(-50%, 0.25rem); transition: opacity var(--dur-short) var(--ease-standard), transform var(--dur-medium) var(--ease-emph);
}
.furn__item:nth-child(-n+2) .furn__name { bottom: auto; top: calc(100% + 22%); } /* top row: label below, so it never leaves the frame */
.furn__item[data-hot] .furn__name { opacity: 1; transform: translate(-50%, 0); }
.furn__dim { margin-block-start: var(--sp-16); }
/* Entrance: icons pop in one after another once the section is on screen (only with JS) */
.js .furn__item { opacity: 0; }
.js .furn.is-in .furn__item { animation: furn-in var(--dur-xl) var(--ease-spring) calc(var(--i) * 70ms + 200ms) both; }
@keyframes furn-in { from { opacity: 0; scale: 0.5; } to { opacity: 1; scale: 1; } }
/* Desktop (square frame), smaller frames: fewer, larger icons (2 + 3 for five, 2 x 2 for four) */
@media (min-width: 64em) {
@container furn (max-width: 19.99rem) {
  .furn__item { --sz: 26%; left: calc(var(--x5) * 1%); top: calc(var(--y5) * 1%); }
  .furn__item:nth-child(n+6) { display: none; }
}
@container furn (max-width: 14.99rem) {
  .furn__item { --sz: 30%; left: calc(var(--x4) * 1%); top: calc(var(--y4) * 1%); }
  .furn__item:nth-child(n+5) { display: none; }
}
}
/* Phones: the frame (icons or photo) is a 4:3 rectangle, so the title, frame and text have more air between them */
@media (max-width: 63.99em) {
  .furn__frame, .step__media > .frame { aspect-ratio: 4 / 3; }
  .furn__item { --sz: 20%; left: calc(var(--lx) * 1%); top: calc(var(--ly) * 1%); }
  .furn__ico svg { width: 68%; height: 68%; }
  .furn__item:nth-child(-n+4) .furn__name { bottom: auto; top: calc(100% + 22%); }
  @container furn (max-width: 17.99rem) {
    .furn__item { --sz: 24%; left: calc(var(--lx5) * 1%); top: calc(var(--ly5) * 1%); }
    .furn__item:nth-child(n+6) { display: none; }
    .furn__item:nth-child(4) .furn__name { top: auto; bottom: calc(100% + 34%); }
  }
  @container furn (max-width: 13.99rem) {
    .furn__item { --sz: 22%; left: calc(var(--lx4) * 1%); top: calc(var(--ly4) * 1%); }
    .furn__item:nth-child(n+5) { display: none; }
    .furn__item:nth-child(3) .furn__name { top: auto; bottom: calc(100% + 34%); }
  }
}
@media (prefers-reduced-motion: reduce) { .js .furn__item { opacity: 1; } .js .furn.is-in .furn__item { animation: none; } }

/* ---------- 18. Home steps (three categories, switched by scrolling) ----------
   Markup: section.steps.themed.theme-X[data-steps][style="--n:3"] > .steps__stage > .steps__top (.opener[data-progress]) + .steps__track >
           article.step[data-theme] > h2.step__title (a) + .step__media + .step__text
   Default (no JS, or reduced motion): the steps are plain stacked themed sections.
   Pinned mode (main.js adds .steps--pinned): the stage sticks to the screen for n screens of scrolling.
     Desktop (64em+): titles list on the left (click = jump), media centre, text right; the active step swaps in.
     Phones: the strip of steps is scrubbed sideways by the vertical scroll; the next step always peeks in (1.5rem). */
.steps { position: relative; transition: background-color 600ms var(--ease-standard), color 600ms var(--ease-standard); }
.steps__top { display: none; }
.step { display: grid; gap: var(--sp-32); padding-block: var(--section-y); padding-inline: max(var(--margin), calc((100% - var(--container)) / 2)); }
.step__title { font-size: var(--fs-h2); }
.step__title a { display: flex; align-items: baseline; gap: var(--sp-16); min-height: 2.75rem; color: inherit; text-decoration: none; transition: color var(--dur-medium) var(--ease-standard); }
.step__title .eyebrow { font-family: var(--font-body); min-width: 2.5ch; flex: none; white-space: nowrap; }
.step__title a:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }
.step__media { display: grid; justify-items: center; align-content: center; }
.step__media > .frame { width: min(100%, 34rem); aspect-ratio: 1; }
.step__text { max-width: 44ch; text-wrap: pretty; }
.step__text > .btn { margin-block-start: var(--sp-24); }
@media (min-width: 64em) {
  .step { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); align-items: center; }
  .step__title { grid-column: 1 / 5; } .step__media { grid-column: 5 / 9; } .step__text { grid-column: 9 / -1; }
  .step__title { font-size: clamp(1.5rem, 1rem + 1.6vw, 2.5rem); }
}

/* Pinned mode */
.steps--pinned { height: calc(100vh + (var(--n) - 1) * 44.444vh); height: calc(100svh + (var(--n) - 1) * 44.444svh); } /* each step = about 0.44 of a screen of scrolling */
.steps--pinned .steps__stage {
  position: sticky; inset-block-start: 0; height: 100vh; height: 100svh; overflow: clip;
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); gap: var(--sp-24);
  padding-block: calc(3.75rem + var(--sp-24)) var(--sp-32);
}
.steps--pinned .steps__top { display: block; width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; }
@media (max-width: 63.99em) {
  .steps--pinned .step { /* phones: the section carries the theme; the step must not paint its own */
    --t-bg: unset; --t-on: unset; --t-faded: unset; --t-logo: unset;
    background: none; color: inherit; padding: 0;
  }
  .steps__bg { display: none; }
}
.steps--pinned .step__title a { color: var(--t-faded); }
.steps--pinned .step[data-active] .step__title a { color: var(--t-on); }
@media (min-width: 64em) {
  /* Desktop: ONE set of three titles (left), and per step a picture and a text that share the same cells.
     Behind them sit three decorative colour layers (.steps__bg, made by JS). The scroll position raises layer n from the bottom edge (--rev 0 to 1,
     a hard edge that can rest half and half). Each picture/text is cut by JS to the part where its own layer is on top, and the text fades while the edge crosses it.
     The titles never move: each one is painted with a fixed gradient with hard stops at the edge positions (--e1, --e2), so every letter changes colour exactly where the edge passes. */
  .steps--pinned .steps__bg { position: absolute; inset: 0; z-index: 0; clip-path: inset(calc((1 - var(--rev, 1)) * 100%) 0 0 0); }
  .steps--pinned .steps__top { position: relative; z-index: 2; }
  .steps--pinned .steps__track {
    position: relative; z-index: 1; width: min(100% - 2 * var(--margin), var(--container)); margin-inline: auto; min-height: 0;
    display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: repeat(var(--n), auto); column-gap: var(--gutter); row-gap: var(--sp-8);
    align-content: center; align-items: center;
  }
  .steps--pinned .step { display: contents; }
  .steps--pinned .step__title { grid-column: 1 / 5; grid-row: var(--r); }
  .steps--pinned .step__media { grid-column: 5 / 9; grid-row: 1 / span var(--n); }
  .steps--pinned .step__text { grid-column: 9 / -1; grid-row: 1 / span var(--n); align-self: center; opacity: var(--tx, 1); }
  .steps--pinned .step .step__title a, .steps--pinned .step[data-active] .step__title a {
    color: var(--t-faded);
  }
  @supports (background-clip: text) or (-webkit-background-clip: text) {
    .steps--pinned .step .step__title a, .steps--pinned .step[data-active] .step__title a {
      color: transparent; -webkit-background-clip: text; background-clip: text; background-attachment: fixed;
      background-image: linear-gradient(to bottom, var(--c0) 0, var(--c0) var(--e1, 100%), var(--c1) var(--e1, 100%), var(--c1) var(--e2, 100%), var(--c2) var(--e2, 100%), var(--c2) 100%);
    }
    .steps--pinned .step:nth-child(1) .step__title a { --c0: var(--on0); --c1: var(--fd1); --c2: var(--fd2); }
    .steps--pinned .step:nth-child(2) .step__title a { --c0: var(--fd0); --c1: var(--on1); --c2: var(--fd2); }
    .steps--pinned .step:nth-child(3) .step__title a { --c0: var(--fd0); --c1: var(--fd1); --c2: var(--on2); }
  }
}
@media (max-width: 63.99em) {
  .steps--pinned { --step: calc(100vw - var(--margin) - 3rem); } /* one slide + gap; the next slide peeks in by 3rem */
  .steps--pinned .steps__track {
    display: flex; gap: var(--sp-16); padding-inline: var(--margin); min-height: 0; align-items: stretch;
    transform: translateX(calc(var(--pos, 0) * var(--step) * -1)); will-change: transform; touch-action: pan-y;
  }
  .steps--pinned .step { display: grid; flex: 0 0 calc(var(--step) - var(--sp-16)); grid-template-rows: auto auto 1fr; gap: var(--sp-24); align-content: start; min-height: 0; }
  .steps--pinned .steps__stage { gap: var(--sp-48); }
  .steps--pinned .step__title a { color: var(--t-on); }
  .steps--pinned .step__media > .frame, .steps--pinned .step__media > .furn { width: min(100%, 34rem, 60vh, 60svh); }
  .steps--pinned .step__text { font-size: var(--fs-body); }
}
@media (max-height: 44em) { .steps--pinned .furn__dim { display: none; } }
/* Short phones (about 700 px or less): tighter stack so the button still fits on one screen */
@media (max-width: 63.99em) and (max-height: 44em) {
  .steps--pinned .steps__stage { gap: var(--sp-24); padding-block-end: var(--sp-16); }
  .steps--pinned .step { gap: var(--sp-12); }
  .steps--pinned .step__media > .frame, .steps--pinned .step__media > .furn { width: min(100%, 34rem, 44vh, 44svh); }
  .steps--pinned .step__text { font-size: 0.9375rem; line-height: 1.5; }
  .steps--pinned .step__text > .btn { margin-block-start: var(--sp-8); min-height: 2.75rem; }
}


/* ==========================================================================
   19 Planks (home, "Els nostres treballs"): three photos side by side, one opens wide (accordion).
   Markup: .frame.planks-frame[data-planks] > a.plank > picture > img[alt]  (the alt text is the link name; no captions or numbers)
   Mouse/keyboard: hover or focus opens a plank. Touch: JS opens them one after another, slowly, and stops after two rounds or on touch.
   ========================================================================== */
.planks-frame {
  --open: 3fr; --ease-soft: cubic-bezier(0.45, 0, 0.2, 1);
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--sp-4); padding: var(--sp-8);
  background-color: color-mix(in srgb, var(--t-on, var(--on-bg)) 8%, var(--t-bg, var(--bg)));
  border: 1px solid color-mix(in srgb, var(--t-on, var(--on-bg)) 45%, transparent);
  transition: grid-template-columns 800ms var(--ease-emph);
}
.plank { position: relative; display: block; min-width: 0; overflow: hidden; background: color-mix(in srgb, var(--t-on, var(--on-bg)) 15%, transparent); }
.plank picture { position: absolute; inset: 0; display: block; }
.plank img { width: 100%; height: 100%; object-fit: cover; display: block; transform: scale(1.02); transition: transform 1000ms var(--ease-emph); }
.planks-frame:has(.plank:nth-child(1):is(:focus-visible, [data-on])) { grid-template-columns: var(--open) 1fr 1fr; }
.planks-frame:has(.plank:nth-child(2):is(:focus-visible, [data-on])) { grid-template-columns: 1fr var(--open) 1fr; }
.planks-frame:has(.plank:nth-child(3):is(:focus-visible, [data-on])) { grid-template-columns: 1fr 1fr var(--open); }
.plank:is(:focus-visible, [data-on]) img { transform: scale(1.06); }
@media (hover: hover) {
  .planks-frame:has(.plank:nth-child(1):hover) { grid-template-columns: var(--open) 1fr 1fr; }
  .planks-frame:has(.plank:nth-child(2):hover) { grid-template-columns: 1fr var(--open) 1fr; }
  .planks-frame:has(.plank:nth-child(3):hover) { grid-template-columns: 1fr 1fr var(--open); }
  .plank:hover img { transform: scale(1.06); }
}
.plank:focus-visible { outline-offset: -3px; z-index: 1; }
/* Phones: wider opening, slower and softer, like a carousel that turns by itself */
@media (hover: none), (max-width: 63.99em) {
  .planks-frame { --open: 4fr; transition-duration: 1400ms; transition-timing-function: var(--ease-soft); }
  .plank img { transition-duration: 2200ms; transition-timing-function: var(--ease-soft); }
}
@media (prefers-reduced-motion: reduce) { .planks-frame, .plank img { transition-duration: 0.01ms; } }

/* ==========================================================================
   20 Central frames, one size for all three steps (icons, planks, visit).
   Desktop: a tall 3:4 portrait; its width is also capped by the screen height so it never crowds the title ruler or the bottom edge.
   Phones: the 4:3 landscape rectangle from above. Every frame, whatever it holds, gets exactly the same box.
   ========================================================================== */
@media (min-width: 64em) {
  .furn__frame, .furn > .frame { aspect-ratio: 3 / 4; }
  .step__media > .frame, .step__media > .furn,
  .steps--pinned .step__media > .frame, .steps--pinned .step__media > .furn { width: min(100%, 34rem, calc((100vh - 16rem) * 0.75), calc((100svh - 16rem) * 0.75)); }
}
@media (max-width: 63.99em) {
  .furn__frame, .furn > .frame { aspect-ratio: 4 / 3; }
}
.furn > .frame { width: 100%; }

/* Phones: every title box is two lines tall (text sits at the bottom), so the three frames start at the same height whatever the title length. */
@media (max-width: 63.99em) {
  .steps--pinned .step > h2.step__title { min-height: 2.16em; display: flex; align-items: flex-end; }
}

/* Links inside the text of a coloured step use the section's text colour (the default link colour is made for the plain page) */
.steps .step__text a:not(.btn) { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; transition: text-decoration-thickness var(--dur-short, 150ms) var(--ease-standard); }
.steps .step__text a:not(.btn):hover { text-decoration-thickness: 2px; }

/* Map (home, "Vine a veure'ns"): the drawing fills the frame; the focus point sits on the workshop marker, so the marker is in view at every frame shape */
.map-frame { background-color: color-mix(in srgb, var(--t-on, var(--on-bg)) 8%, var(--t-bg, var(--bg))); border: 1px solid color-mix(in srgb, var(--t-on, var(--on-bg)) 45%, transparent); }
.map-frame img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; object-position: 66.4% 75.5%; }
a.map-frame { cursor: pointer; text-decoration: none; }
.map-frame img { transition: transform 900ms var(--ease-emph); transform-origin: 66.4% 75.5%; }
@media (hover: hover) { a.map-frame:hover img { transform: scale(1.05); } }
a.map-frame:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }
@media (prefers-reduced-motion: reduce) { .map-frame img { transition: none; } a.map-frame:hover img { transform: none; } }

/* ---------- 21. Gallery hub & category pages (Phase 4) ----------
   Hub: photo band (hero--band) + a "word wall" on graph paper (ul.wall): every category is a link made of  icon · title.
   Desktop: running display type; hover/focus dims the others and highlights one in coral (the same coral for all: these pages use the site palette).
   Phones (< 48em): one row per category, ruled like an index; a tap/press wipes the row to coral.
   Shared: .crumbs (visible breadcrumb for the category pages, same trail as their BreadcrumbList JSON-LD). */
.gal-main { overflow-x: clip; } /* nothing may cause sideways scroll; clip (not hidden) keeps position: sticky working (chip row of the category pages) */
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; list-style: none; margin: 0; padding: 0;
  font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; }
.crumbs li:not(:last-child)::after { content: "/"; content: "/" / ""; margin-inline: 0.75em; opacity: 0.6; } /* the slash ends a line, so a wrapped trail never starts with one */
.crumbs a { display: inline-flex; align-items: center; min-height: 2.75rem; color: inherit; text-decoration: none; }
.crumbs a:hover { text-decoration: underline; text-underline-offset: 0.3em; }
.crumbs [aria-current="page"] { opacity: 0.78; }
/* Photo band: the home hero photo, short, with the H1 inside (hub, Sobre nosaltres, Contacte).
   Header: data-logo="light" (transparent, white logo) until the page scrolls, then the usual solid bar. Same <picture> files as the home hero, so they are already cached.
   Height = content: room for the 152 px logo at the top, the H1, and the ruler along the bottom edge. */
.hero--band { min-height: 0; }
.hero--band .hero__inner { padding-block: calc(var(--mark-h-top) + clamp(var(--sp-64), 2.5rem + 4vw, var(--sp-96))) calc(var(--sp-48) + 14px); } /* clear space between the logo and the H1: 64 px on phones, 96 px on desktop */
.hero--band .hero__title { max-width: none; }
.hero--band .hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 60% 50%; }
/* One shared origin for all the graph-paper measures: the band's ruler, the paper under the content and the footer's paper + ruler all start at the viewport's left edge,
   so their 1 / 5 / 10 module lines (8 / 40 / 80 px) fall on the same verticals at every width. */
.hero--band .hero__ruler .ruler { width: 100%; margin-inline: 0; }
.gal-body > .paper-bg { background-position: left top; }
.crumbs + h1 { margin-block-start: var(--sp-16); }
.gal-body { padding-block: var(--sp-48) var(--section-y); }
.gal-intro { max-width: 38ch; margin-block-end: var(--sp-48); text-wrap: balance; }

/* Word wall */
.wall { --hl: var(--brand); --hl-on: var(--on-brand);
  list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr);
  font-family: var(--font-display); font-size: clamp(1.625rem, 1.15rem + 2.1vw, 2rem); line-height: 1.2; }
.wall a { position: relative; isolation: isolate; display: grid; grid-template-columns: 1.75rem minmax(0, 1fr); align-items: center; gap: var(--sp-16);
  min-height: 4.5rem; padding: var(--sp-8) var(--sp-8); color: var(--on-bg); text-decoration: none; -webkit-tap-highlight-color: transparent; }
.wall a::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--hl); clip-path: inset(100% 0 0 0); transition: clip-path 520ms var(--ease-emph); }
.wall__t { text-wrap: balance; }
.wall__ico { width: 1.75rem; height: 1.75rem; fill: currentColor; flex: none; transition: transform 600ms var(--ease-spring); } /* icon stays smaller than the title text, also when it grows on hover */
.wall a:active, .wall a:focus-visible { color: var(--hl-on); --focus: var(--hl-on); }
.wall a:active::before, .wall a:focus-visible::before { clip-path: inset(0); }
.wall a:focus-visible { outline-offset: -3px; }
@media (hover: hover) {
  .wall a:hover { color: var(--hl-on); }
  .wall a:hover::before { clip-path: inset(0); }
  .wall a:hover .wall__ico { transform: scale(1.12); }
}
/* From 48em: a running wall of big type. Items stay whole; the row-by-row index becomes a sentence. */
@media (min-width: 48em) {
  .wall { display: flex; flex-wrap: wrap; gap: 0.16em 0.5em; font-size: clamp(2.25rem, 0.5rem + 3.6vw, 4rem); letter-spacing: -0.01em; }
  .wall a { display: inline-flex; align-items: center; gap: 0.18em; min-height: 0; padding: 0.06em 0.16em 0.1em; transition: opacity var(--dur-medium) var(--ease-standard), color var(--dur-medium) var(--ease-standard); }
  .wall a::before { clip-path: none; opacity: 0; transition: opacity var(--dur-medium) var(--ease-standard); }
  .wall a:active::before, .wall a:focus-visible::before { opacity: 1; }
  .wall__t { text-wrap: wrap; }
  .wall a { align-items: flex-start; }
  .wall__ico { width: 0.5em; height: 0.5em; margin-block-start: 0.21em; } /* top-aligned with the capitals; icons are re-framed to equal visual size in the markup */
}
@media (min-width: 48em) and (hover: hover) {
  .wall:has(a:hover) a:not(:hover), .wall:has(a:focus-visible) a:not(:focus-visible) { opacity: 0.25; }
  .wall a:hover::before { clip-path: none; opacity: 1; }
}

/* ---- Category pages ----
   Band: .hero--solid = a coloured band (theme class on the same element, here .theme-container) instead of a photo; same size and ruler as the photo band. */
.hero--solid { color: var(--t-on); --focus: var(--t-on); }
.hero--solid::before { content: none; }
.hero--solid .hero__ruler { color: var(--t-on); }
.hero--solid .crumbs [aria-current="page"] { opacity: 1; }
/* Chip row: the 11 categories, sticky under the header once it has collapsed (44 + 2 x 8 px). Its own tone, off the collapsed header bar (#f4ece9 / #2a2522): lighter in light mode (white), darker in dark mode, no border.
   One line that scrolls sideways when it does not fit: a soft fade marks each cut-off edge, and on laptop/desktop a round arrow button appears there while the pointer is over the bar (main.js). */
.chips { --chips-bg: light-dark(#ffffff, #201a18); position: sticky; inset-block-start: calc(2.75rem + 2 * var(--sp-8)); z-index: var(--z-raised);
  background: var(--chips-bg); }
.chips ul { position: relative; display: flex; gap: var(--sp-12); list-style: none; margin: 0; padding-block: var(--sp-24);
  padding-inline: max(var(--margin), calc((100% - var(--container-wide)) / 2));
  overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
.chips ul::-webkit-scrollbar { display: none; }
.chips li { flex: none; }
.chips a { display: inline-flex; align-items: center; min-height: 2.75rem; padding-inline: var(--sp-12); border: 1px solid var(--outline-variant); border-radius: 999px;
  color: var(--on-bg); text-decoration: none; font-size: var(--fs-label); font-weight: 500; white-space: nowrap;
  transition: background-color var(--dur-medium) var(--ease-standard), border-color var(--dur-medium) var(--ease-standard), color var(--dur-medium) var(--ease-standard); }
@media (hover: hover) { .chips a:hover { border-color: var(--on-bg); } }
.chips a[aria-current="page"] { background: var(--brand); border-color: var(--brand); color: var(--on-brand); font-weight: 600; }
/* Section icon inside the chip: open on the current page's chip; on any other chip it opens only while hovered / keyboard-focused, so the chip stretches
   with a springy (Material 3 expressive) overshoot and shows that section's icon. Touch screens have no hover: only the current chip shows its icon. */
.chips__ico { flex: none; width: 0; height: 1.25rem; margin-inline-end: 0; opacity: 0; transform: scale(0.5); fill: currentColor; overflow: visible;
  transition: width 560ms var(--ease-spring), margin-inline-end 560ms var(--ease-spring), transform 560ms var(--ease-spring), opacity var(--dur-medium) var(--ease-standard); }
.chips a[aria-current="page"] .chips__ico, .chips a:focus-visible .chips__ico { width: 1.25rem; margin-inline-end: var(--sp-8); opacity: 1; transform: none; }
@media (hover: hover) { .chips a:hover .chips__ico { width: 1.25rem; margin-inline-end: var(--sp-8); opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .chips__ico { transition: none; } }
/* Ripple on press (main.js adds <span class="chips__ripple"> at the pointer position; the chip clips it to its pill shape) */
.chips a { position: relative; overflow: hidden; isolation: isolate; }
.chips__ripple { position: absolute; z-index: -1; border-radius: 50%; background: currentColor; opacity: 0.16; pointer-events: none; transform: scale(0); animation: chips-ripple 650ms var(--ease-decel) forwards; }
@keyframes chips-ripple { to { transform: scale(1); opacity: 0; } }
.chips::before, .chips::after { content: ""; position: absolute; inset-block: 0; width: clamp(3rem, 8vw, 6rem); z-index: 1; pointer-events: none; opacity: 0; transition: opacity var(--dur-medium) var(--ease-standard); }
.chips::before { inset-inline-start: 0; background: linear-gradient(to right, var(--chips-bg) 15%, transparent); }
.chips::after { inset-inline-end: 0; background: linear-gradient(to left, var(--chips-bg) 15%, transparent); }
.chips[data-more-start]::before, .chips[data-more-end]::after { opacity: 1; }
.chips__btn { display: none; }
@media (hover: hover) {
  .chips__btn { position: absolute; inset-block-start: 50%; z-index: 2; display: grid; place-items: center; width: 2.75rem; height: 2.75rem; margin-block-start: -1.375rem; padding: 0;
    border: 0; border-radius: 50%; background: var(--btn-bg, light-dark(#e9dfdb, #43393a)); color: var(--on-bg); cursor: pointer; box-shadow: 0 2px 8px rgb(0 0 0 / 0.12); /* darker than the bar in light mode, lighter in dark mode */
    opacity: 0; pointer-events: none; transition: opacity var(--dur-medium) var(--ease-standard), background-color var(--dur-medium) var(--ease-standard); }
  .chips__btn svg { width: 1.25rem; height: 1.25rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  .chips__btn--prev { inset-inline-start: var(--sp-16); } .chips__btn--next { inset-inline-end: var(--sp-16); }
  .chips[data-more-start]:hover .chips__btn--prev, .chips[data-more-end]:hover .chips__btn--next { opacity: 1; pointer-events: auto; }
  .chips__btn:hover { background: light-dark(#ddd0cb, #54484a); }
}
/* Photos in a "river": a dense grid of 3:2 cells. A horizontal photo takes 1 cell (3:2), a vertical photo 1 cell wide and 2 tall (about 2:3),
   a highlighted photo (li.is-hl) 2 x 2 cells; grid-auto-flow: dense lets the small photos fill the gaps around the big ones, so nothing is left empty.
   Columns: 1 / 2 / 3 / 4 (phones, tablet, laptop, wide) = one column fewer than the home .gallery grid, in the wide container.
   On phones everything is one column at its natural shape. */
.gal-body--cat { padding-block: var(--sp-32) var(--section-y); }
.gal-grid { --n: 1; --gap: var(--sp-24); --W: min(100vw - 2 * var(--margin), var(--container-wide));
  --cell: calc((var(--W) - (var(--n) - 1) * var(--gap)) / var(--n) / 1.5);   /* height of one cell: a 3:2 photo one column wide */
  display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); grid-auto-flow: dense; gap: var(--gap); }
@media (min-width: 48em) { .gal-grid { --n: 2; --gap: var(--sp-12); grid-auto-rows: var(--cell); } }
@media (min-width: 64em) { .gal-grid { --n: 3; } }
@media (min-width: 80em) { .gal-grid { --n: 4; --gap: var(--sp-16); } }
.gal-grid > li { --ar: 1.5; min-width: 0; }
.gal-grid > li.is-v { --ar: 0.6667; }
.gal-grid .frame { margin: 0; aspect-ratio: var(--ar); }
@media (min-width: 48em) {
  .gal-grid > li.is-v { grid-row: span 2; }
  .gal-grid > li.is-hl { grid-column: span 2; grid-row: span 2; }
  .gal-grid .frame { aspect-ratio: auto; height: 100%; }
}
.gal-grid picture { display: block; width: 100%; height: 100%; }
.gal-grid .frame img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 1100ms var(--ease-emph); will-change: transform; }
@media (hover: hover) { .gal-grid .frame:hover img { transform: scale(1.08); } }
@media (prefers-reduced-motion: reduce) { .gal-grid .frame img { transition: none; } .gal-grid .frame:hover img { transform: none; } }

/* ---- Closing contact band on category pages: sage in light mode, moss in dark mode (the two themes follow the colour scheme), one line on desktop, stacked on phones ---- */
.cta { --t-bg: light-dark(#b9cba3, #2f3b20); --t-on: light-dark(#18220d, #eef3e2); --t-faded: light-dark(#3f5329, #aebd8f); padding-block: clamp(2.5rem, 1.75rem + 3.2vw, 4.75rem); }
.cta__inner { display: grid; gap: var(--sp-24) var(--sp-48); align-items: center; justify-items: start; }
.cta__title { margin: 0; text-wrap: balance; }
@media (min-width: 64em) { .cta__inner { grid-template-columns: 1fr auto; } }

/* ---------- 22. Sobre nosaltres (Phase 4) ----------
   Photo band (hero--band, like the hub) -> introduction + "what we do" on the graph paper (.about) -> "La nostra fórmula" on a terracotta band (.formula) -> the closing .cta band. */
.about-main { overflow-x: clip; }
.about { container-type: inline-size; padding-block: calc(var(--paper-unit) * 8) var(--section-y); }   /* container-type: lets the plan read the section width (cqw) to snap to the grid */
.about > .paper-bg { background-position: left top; }
.about__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-48); }
.about__lead { margin: 0; max-width: 28em; font-family: var(--font-display); font-size: clamp(1.625rem, 1.05rem + 2.3vw, 3rem); line-height: 1.18; line-height: round(nearest, 1.18em, var(--paper-unit)); letter-spacing: -0.008em; text-wrap: pretty; }
.about__text { margin: 0; max-width: var(--measure); text-wrap: pretty; hyphens: auto; }
.about__text a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; transition: text-decoration-thickness var(--dur-short, 150ms) var(--ease-standard); }
.about__text a:hover { text-decoration-thickness: 2px; }
.about__text a:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
@media (min-width: 64em) {
  .about__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: calc(var(--paper-unit) * 8); }
  .about__lead { grid-column: 1 / span 10; }
  .about__text { grid-column: 6 / -1; }
}
/* Marker bar on the key phrases of the two main paragraphs (<mark class="bar" style="--i:n">): a translucent brand-coral bar grows from left to right once its paragraph has appeared,
   the graph paper shows through it, it wraps over lines (box-decoration-break: clone). Reduced motion: shown at once. Forced colours: the system highlight colours. */
.about mark.bar { color: inherit; padding-inline: 0.18em 0.06em; margin-inline: -0.18em -0.06em; -webkit-box-decoration-break: clone; box-decoration-break: clone;
  background: linear-gradient(transparent 14%, color-mix(in srgb, var(--brand) 34%, transparent) 14% 90%, transparent 90%) left center / 100% 100% no-repeat;
  transition: background-size 0.9s var(--ease-emph) calc(var(--i) * 0.35s + 0.5s); }
.js .about [data-reveal]:not(.is-in) mark.bar { background-size: 0% 100%; }
@media (prefers-reduced-motion: reduce) { .about mark.bar { transition: none; } .js .about [data-reveal]:not(.is-in) mark.bar { background-size: 100% 100%; } }
@media (forced-colors: active) { .about mark.bar { background: Mark; color: MarkText; } }
/* Secondary tone (the palette's secondary container: warm sand in light mode, deep brown in dark mode), sitting between the paper above and the sage / moss closing band below. */
.theme-secondary { --t-bg: light-dark(#fedcc7, #3a2414); --t-on: light-dark(#2d1600, #fedcc7); --t-faded: light-dark(#7e553b, #eebc9e); }
.formula { padding-block: 0 var(--section-y); }
.formula__ruler { width: 100%; color: var(--t-faded); transform: scaleY(-1); }   /* ruler hanging from the top edge, like the CTA band recipe */
.formula__title { margin-block: var(--sp-64) var(--sp-48); text-wrap: balance; }
.formula__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-48); }
.formula__item { display: grid; align-content: start; gap: var(--sp-16); }
.formula__item p { margin: 0; text-wrap: pretty; }
.formula__n { font-family: var(--font-display); font-size: var(--fs-h2); line-height: 1; color: var(--t-faded); font-variant-numeric: tabular-nums; }
/* Above each statement: a dimension line (├── icon ──┤, the .dim component) whose label is the owner's step icon (design / screw / drill), small and in the line's own colour, decorative.
   It draws in from the left like the other rules (data-draw), one column after the other. */
.formula__dim { color: var(--t-faded); margin-block-end: var(--sp-8); gap: var(--sp-16); --d: 0; }
.formula__item:nth-child(2) .formula__dim { --d: 1; } .formula__item:nth-child(3) .formula__dim { --d: 2; }
.js .formula__dim[data-draw] { transition-delay: calc(var(--d) * 0.25s); }
.formula__ico { flex: none; width: 1.5rem; height: 1.5rem; fill: currentColor; }
@media (min-width: 64em) { .formula__list { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--gutter); } }

/* Floor plan in the empty space left of the second paragraph (>= 80em only, decorative). Drawn in grid units (1 unit = 8 px = one paper cell) at its natural size (400 x 280 px):
   the room is 50 x 35 units, so its walls fall on the second-boldest paper lines once the top-left corner sits on a boldest line. main.js measures the plan against
   the paper and sets --plan-dx / --plan-dy (always >= 0, < 80 px) to push it onto the next bold crossing; until then (or without JS) it sits on its grid cell.
   Animation (once, when ~40% of it is on screen): the walls are laid first, each strip growing from the corner, clockwise; then the windows and door, then the furniture
   zone by zone (kitchen, island, dining, living), each outline drawn as one pen stroke, like a draughtsman. Reduced motion: shown at once. */
.about__plan { display: none; width: 400px; color: var(--on-bg); margin-inline-start: var(--plan-dx, 0px); margin-block-start: var(--plan-dy, 0px); }   /* hidden while the paragraphs take the full width */
@media (min-width: 64em) {   /* as soon as the paragraph leaves the left side free: the plan sits in that space */
  .about__plan { display: block; grid-column: 1 / span 5; grid-row: 2; align-self: start; }
  .about__text { grid-row: 2; }
}
@media (min-width: 64em) and (max-width: 79.99em) { .about__text { grid-column: 7 / -1; } }   /* one column narrower at laptop widths, so the 400 px plan fits beside it */
.plan { display: block; overflow: visible; }
.plan__w { fill: currentColor; transform-box: fill-box;
  transition: transform 0.55s cubic-bezier(.45, 0, .2, 1) calc(0.2s + var(--w) * 0.22s); }
.plan__f, .plan__t { fill: none; stroke: currentColor; stroke-width: 0.25; stroke-linejoin: miter; }
.plan__t { stroke-width: 0.125; }
/* Each outline is drawn by growing a dash along it (pathLength="1"); it is hidden (zero-length dash) until its turn. The dash only exists DURING the animation
   (fill-mode backwards): when it ends the shape is a normal solid stroke again, so corners join cleanly and circles are perfectly closed. */
.js .about__plan .plan__f, .js .about__plan .plan__t { stroke-dasharray: 0 1.2; }
.js .about__plan.is-in .plan__f, .js .about__plan.is-in .plan__t { stroke-dasharray: none; animation: plan-draw 0.7s cubic-bezier(.5, 0, .25, 1) calc(2s + var(--i) * 0.07s) backwards; }
.js .about__plan.is-in .plan__t { animation-duration: 0.45s; }
@keyframes plan-draw { from { stroke-dasharray: 0 1.2; } to { stroke-dasharray: 1.2 0; } }
.js .about__plan:not(.is-in) .plan__w--h { transform: scaleX(0); }
.js .about__plan:not(.is-in) .plan__w--v { transform: scaleY(0); }
@media (prefers-reduced-motion: reduce) { .plan__w { transition: none; } .js .about__plan:not(.is-in) .plan__w { transform: none; }
  .js .about__plan .plan__f, .js .about__plan .plan__t, .js .about__plan.is-in .plan__f, .js .about__plan.is-in .plan__t { stroke-dasharray: none; animation: none; } }

/* ---------- 23. Contacte (Phase 4) ----------
   Photo band (hero--band) -> .contact on the solid page colour. Phones: .contact__info (paragraph + data) > .contact__form (graph paper + the form sheet) > .contact__map.
   Desktop (>= 64em): two halves, edge to edge: left = info with the map under it, right = the paper panel with the sheet (areas "info form" / "map form").
   Grid rules: the paper starts at its panel's top-left corner; the sheet's left/top edges lie on bold lines (80 px; 40 px on tablets, 16 px on phones), its width is rounded
   down to a multiple of the mid line (40 px; 8 px on phones) and main.js rounds its height up to the next one. */
.contact-main { overflow-x: clip; }
.contact { display: grid; grid-template-columns: minmax(0, 1fr); background: var(--bg); }
.contact__info { padding: var(--sp-48) var(--margin) var(--sp-48); }
.contact__lead { margin: 0; max-width: 36rem; text-wrap: pretty; }
/* Quick-action tiles (phone, WhatsApp, email, Google Maps): solid squares, no paper; the plain data lines sit under them */
.contact__tiles { list-style: none; margin: var(--sp-32) 0 0; padding: 0; max-width: 36rem; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-12); }
.contact__tiles li { display: grid; }
.contact__tile { min-height: 5.75rem; display: grid; grid-template-rows: 1fr auto; justify-items: center; align-items: center; padding: var(--sp-12) var(--sp-8); text-align: center;
  background: var(--surface-lowest); color: var(--on-bg); border: 1px solid var(--outline); text-decoration: none;
  transition: background-color var(--dur-short, 150ms) var(--ease-standard), color var(--dur-short, 150ms) var(--ease-standard), border-color var(--dur-short, 150ms); }
.contact__tile > span { font-size: var(--fs-eyebrow); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.2; }
@media (max-width: 47.99em) { .contact__tile { padding-inline: 4px; } .contact__tile > span { font-size: 0.6875rem; letter-spacing: 0.04em; } }
@media (min-width: 48em) { .contact__tile { aspect-ratio: 1; min-height: 0; } }
.contact__ico { width: 2rem; height: 2rem; fill: var(--brand); transition: transform var(--dur-medium, 300ms) var(--ease-spring, ease), fill var(--dur-short, 150ms); }
.contact__tile:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
@media (hover: hover) {
  .contact__tile:hover { background: var(--primary-container); color: var(--on-primary-container); border-color: var(--primary); }
  .contact__tile:hover .contact__ico { fill: currentColor; transform: translateY(-3px) scale(1.12); }
}
@media (prefers-reduced-motion: reduce) { .contact__tile, .contact__ico { transition: none; } .contact__tile:hover .contact__ico { transform: none; } }
.contact__lines { margin-top: var(--sp-32); max-width: 36rem; display: grid; gap: var(--sp-16); font-family: var(--font-display); font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem); line-height: 1.3; overflow-wrap: anywhere; }
.contact__lines p { margin: 0; }
.contact__lines address { font-style: normal; }
.contact__lines a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; transition: text-decoration-thickness var(--dur-short, 150ms) var(--ease-standard); }
.contact__lines a:hover { text-decoration-thickness: 2px; }
.contact__lines a:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
/* Paper panel + sheet */
.contact__form { background: var(--surface-low); }   /* same ground as the footer, so the paper reads the same */
.contact__form > .paper-bg { background-position: left top; }   /* the panel's left edge is a multiple of 80 px from the page edge (see the grid below), so its lines continue the footer's */
.contact__sheet { container-type: inline-size; margin: 16px 0 16px 16px; width: calc(100% - 32px); width: round(down, calc(100% - 32px), 8px);
  padding: 24px; background: var(--surface-lowest); border: 1px solid var(--outline); }
.contact__sheet-in { display: grid; gap: var(--sp-24); }
.contact__sheet-in > h2 { margin: 0; }
.contact__fields { display: grid; gap: var(--sp-24); }
.contact__pair { display: grid; gap: var(--sp-24); }
.contact__opt { font-weight: 400; color: var(--on-surface-variant); }
.contact__fields .check a { color: inherit; text-decoration: underline; text-underline-offset: 0.2em; }
@container (min-width: 30rem) { .contact__pair { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.contact__map .frame { aspect-ratio: 4 / 3; border: 0; }
@media (min-width: 48em) {
  .contact__info { padding-block: var(--sp-64); }
  .contact__sheet { margin: 40px 0 40px 40px; width: calc(100% - 120px); width: round(down, calc(100% - 80px), 40px); padding: 40px; }
  .contact__map .frame { aspect-ratio: 16 / 9; }
}
@media (min-width: 64em) {
  .contact { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: minmax(0, round(down, 50%, 80px)) minmax(0, 1fr); grid-template-rows: auto 1fr; grid-template-areas: "info form" "map form"; }
  .contact__info { grid-area: info; padding-block: 80px 64px; padding-inline: max(var(--margin), calc((100vw - var(--container)) / 2)) clamp(2rem, 4vw, 5rem); }
  .contact__form { grid-area: form; }
  .contact__map { grid-area: map; min-height: clamp(20rem, 30vw, 30rem); }
  .contact__map .frame { aspect-ratio: auto; height: 100%; }
  .contact__sheet { margin: 80px 0 80px 80px; width: calc(100% - 120px); width: round(down, calc(100% - 120px), 40px); }
}

/* ---------- 24. Pàgines legals (Phase 4) ----------
   Photo band (hero--band) -> .legal: plain page colour, ONE reading column (65ch, left-aligned with the header logo), no paper, no sheet, no dividers -> the closing band (.cta--home), its button centred. */
.legal-main { overflow-x: clip; }
.legal { padding-block: var(--sp-64) var(--section-y); }
.legal__body { max-width: var(--measure); text-wrap: pretty; hyphens: auto; }
.legal__body > * + * { margin-block-start: 1em; }
.legal__body h2 { margin-block-start: 2.5em; font-size: var(--fs-h3); line-height: 1.2; text-wrap: balance; hyphens: manual; }
.legal__body h3 { margin-block-start: 1.75em; font-family: var(--font-body); font-size: var(--fs-body-l); font-weight: 600; line-height: 1.35; text-wrap: balance; hyphens: manual; }
.legal__body > h2:first-child, .legal__tools + h2 { margin-block-start: 0; }
.legal__body h2 + h3 { margin-block-start: 1em; }
.legal__body h2 + *, .legal__body h3 + * { margin-block-start: 0.75em; }
.legal__body ul { padding-inline-start: 1.25rem; }
.legal__body li + li { margin-block-start: 0.5em; }
.legal__body ul.legal__data { list-style: none; padding: 0; }
.legal__body ul.legal__data li + li { margin-block-start: 0.25em; }
.legal__body p { overflow-wrap: anywhere; }
.legal__tools { margin-block-end: var(--sp-32); }
.cta--home .cta__inner { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; }

/* ---------- 25. Pàgina 404 (Phase 4) ----------
   One block on the graph paper (same origin as the footer's paper, so the lines continue), everything centred: numeral, dimension line, H1, line, two buttons.
   Header = logo only (data-solid). Generous space above and below. Markup: main.err-main > section.err.paper-host > .paper-bg + .container > .err__num + h1 + p + .err__actions. */
.err-main { overflow-x: clip; }
.err { padding-block: calc(var(--mark-h-top) + clamp(6rem, 14vw, 12rem)) clamp(8rem, 16vw, 15rem); text-align: center; }
.err > .paper-bg { background-position: left top; }
.err__numwrap { display: inline-block; max-width: 100%; }
.err__num { font-size: clamp(7rem, 22vw, 16rem); line-height: 0.9; margin: 0; }
.err__numwrap .dim { margin-block: var(--sp-16); }
.err__lead { margin-block-start: var(--sp-16); text-wrap: balance; }
.err__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-12, 12px); margin-block-start: var(--sp-24); }
