/* ==========================================================================
   Hamlet Digital — public site stylesheet

   Built from the Claude Design handoff in design/hamlet-digital-redesign.
   Values (sizes, clamp()s, radii, colours) are copied from the prototypes,
   so a section converted from a .dc.html file should look identical.

   Order:
     1. Tokens          custom properties — every colour, radius, shadow, font
     2. Base            reset and element defaults
     3. Layout          page gutter, sections, grids, stacks
     4. Type            headings, lede, highlight
     5. Components      buttons, arrow badge, chips, cards, hero, bubbles,
                        forms, blobs, image placeholder, FAQ, motion helpers
     6. Shell           header, mega-menus, mobile nav, skyline, footer,
                        cookie banner, WhatsApp float, back-to-top, toast
     7. Shared pages    stub, error pages, prose

   Page-specific CSS does NOT go here: it lives in
   /assets/css/pages/<page>.css and is loaded by the layout when a page asks
   for it ($pageCss). See design/FRONTEND-NOTES.md.

   CSP: style-src 'self'. No style="" attributes and no <style> blocks
   anywhere — they are silently dropped by the browser.
   ========================================================================== */


/* ==========================================================================
   1. Tokens
   ========================================================================== */

:root {
    /* Brand colours (Brand Guide §2) */
    --c-teal: #28D2D5;           /* hero backgrounds, active states */
    --c-pink: #e5336f;           /* logo, primary buttons, shapes */
    --c-pink-text: #b8174f;      /* pink as TEXT (AA contrast) */
    --c-yellow: #ffc93c;         /* highlights, badges, CTA blocks */
    --c-ink: #3b1758;            /* all text, borders and shadows */
    --c-cream: #fff8f1;          /* page background */
    --c-lilac: #c9b3f2;
    --c-orange: #f7883b;
    --c-white: #fff;

    /* Tints — card backgrounds only */
    --c-yellow-tint: #ffeeb8;
    --c-pink-tint: #fcd6e2;
    --c-teal-tint: #c9f3f4;
    --c-lilac-tint: #ece2fb;
    --c-orange-tint: #fde0c8;

    /* Supporting shades used by the prototypes */
    --c-ink-deep: #1a0a24;       /* button label colour */
    --c-ink-night: #1f0b30;      /* skyline window "lights off" */
    --c-muted: #5f4a73;          /* secondary text in menus */
    --c-line: #f1e6f7;           /* menu dividers, small badges */
    --c-yellow-tint-hover: #ffe59a;
    --c-yellow-hover: #ffe28a;
    --c-teal-tint-hover: #b5eef0;
    --c-switch-off: #e8dcd2;
    --c-whatsapp: #25D366;
    --c-overlay: rgba(59, 23, 88, 0.45);

    /* Type */
    --f-display: 'Bricolage Grotesque', Figtree, sans-serif;
    --f-body: Figtree, sans-serif;
    --f-mono: ui-monospace, monospace;

    /* Layout */
    --gutter: clamp(20px, 4vw, 56px);

    /* Radii */
    --r-pill: 99px;
    --r-hero: 48px;
    --r-panel: 40px;
    --r-dialog: 36px;
    --r-banner: 32px;
    --r-card: 28px;
    --r-bubble: 22px 22px 22px 6px;
    --r-tile: 22px;
    --r-item: 18px;
    --r-field: 16px;
    --r-shot: 14px;

    /* Solid offset shadows — the design's "chunky" look */
    --sh-ink: 0 8px 0 var(--c-ink);
    --sh-ink-sm: 0 6px 0 var(--c-ink);
    --sh-ink-xs: 0 5px 0 var(--c-ink);

    /* Motion */
    --ease-spring: cubic-bezier(.34, 1.6, .5, 1);
    --ease-pop: cubic-bezier(.34, 1.7, .5, 1);
}

/* Tint helpers. Each sets --tint (for components that derive from it, like
   the product preview's stripes) and paints it as the background. */
.tint-yellow { --tint: var(--c-yellow-tint); background-color: var(--tint); }
.tint-pink   { --tint: var(--c-pink-tint);   background-color: var(--tint); }
.tint-teal   { --tint: var(--c-teal-tint);   background-color: var(--tint); }
.tint-lilac  { --tint: var(--c-lilac-tint);  background-color: var(--tint); }
.tint-orange { --tint: var(--c-orange-tint); background-color: var(--tint); }
.tint-cream  { --tint: var(--c-cream);       background-color: var(--tint); }
.tint-white  { --tint: var(--c-white);       background-color: var(--tint); }

/* Solid brand backgrounds */
.bg-teal   { background-color: var(--c-teal); }
.bg-pink   { background-color: var(--c-pink); }
.bg-yellow { background-color: var(--c-yellow); }
.bg-lilac  { background-color: var(--c-lilac); }
.bg-orange { background-color: var(--c-orange); }
.bg-ink    { background-color: var(--c-ink); color: var(--c-cream); }
.bg-cream  { background-color: var(--c-cream); }
.bg-white  { background-color: var(--c-white); }


/* ==========================================================================
   2. Base
   ========================================================================== */

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

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

body {
    margin: 0;
    background: var(--c-cream);
    font-family: var(--f-body);
    color: var(--c-ink);
    -webkit-font-smoothing: antialiased;
}

/* The prototypes set margin:0 on every heading and paragraph; doing it once
   here means converted markup needs no margin rules. Long-form copy gets its
   spacing back inside .prose. */
h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }

a { color: var(--c-ink); text-decoration: none; }
a:hover { color: var(--c-pink-text); }

img, svg, video { max-width: 100%; }
img { height: auto; }

button, input, select, textarea { font: inherit; }

:focus-visible { outline: 3px solid var(--c-ink); outline-offset: 3px; border-radius: 8px; }

::selection { background: var(--c-yellow); color: var(--c-ink); }

/* `hidden` must win over any component's display rule, or toggling it from
   script silently does nothing. */
[hidden] { display: none !important; }

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

/* Scroll lock while a modal (cookie preferences) is open. */
.is-modal-open, .is-modal-open body { overflow: hidden; }


/* ==========================================================================
   3. Layout
   ========================================================================== */

.page { min-height: 100vh; display: flex; flex-direction: column; }
.main { flex: 1 0 auto; display: flex; flex-direction: column; }

/* Sections carry the page gutter and their top spacing; the bottom is
   always 0 — the next section's top (or the skyline's 112px) provides it. */
.section       { padding: 112px var(--gutter) 0; }
.section--96   { padding-top: 96px; }
.section--72   { padding-top: 72px; }
.section--56   { padding-top: 56px; }
.section--48   { padding-top: 48px; }
.section--hero { padding-top: 16px; }

/* Anchor targets clear the top of the viewport a little. */
[id] { scroll-margin-top: 16px; }

/* Flex column stacks — the prototypes' "display:flex;flex-direction:column;gap:N" */
.stack     { display: flex; flex-direction: column; }
.gap-6     { gap: 6px; }
.gap-8     { gap: 8px; }
.gap-10    { gap: 10px; }
.gap-12    { gap: 12px; }
.gap-14    { gap: 14px; }
.gap-16    { gap: 16px; }
.gap-20    { gap: 20px; }
.gap-24    { gap: 24px; }
.gap-28    { gap: 28px; }
.gap-32    { gap: 32px; }
.gap-40    { gap: 40px; }

.row       { display: flex; flex-wrap: wrap; align-items: center; }

.max-560 { max-width: 560px; }
.max-600 { max-width: 600px; }
.max-640 { max-width: 640px; }
.max-760 { max-width: 760px; }

/* Auto-fitting card grids: repeat(auto-fit, minmax(min(100%, N), 1fr)) */
.grid     { display: grid; gap: 16px; }
.grid-200 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.grid-220 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.grid-240 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.grid-260 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.grid-280 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }
.grid-300 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid-340 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }
.grid-420 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); }

/* The prototypes' [data-g4]: four columns, two under 1100px, one under 560px. */
.grid-4 { display: grid; gap: 16px; grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .grid-4 { grid-template-columns: minmax(0, 1fr); } }

/* [data-legal-art]: decorative art that only fits on wide screens */
@media (max-width: 1100px) { .hide-below-1100 { display: none !important; } }


/* ==========================================================================
   4. Type
   ========================================================================== */

.display { font-family: var(--f-display); font-weight: 800; }

/* Hero heading — Contact/About/Brand pages */
.h1 {
    font-family: var(--f-display); font-weight: 800;
    font-size: clamp(48px, 7vw, 96px); line-height: 0.95; letter-spacing: -0.03em;
}

/* Section heading */
.h2 {
    font-family: var(--f-display); font-weight: 800;
    font-size: clamp(36px, 4.5vw, 56px); line-height: 1; letter-spacing: -0.025em;
}

/* Smaller section / panel heading */
.h2-sm {
    font-family: var(--f-display); font-weight: 800;
    font-size: clamp(32px, 3.5vw, 44px); line-height: 1; letter-spacing: -0.02em;
}

/* Card heading */
.h3 { font-family: var(--f-display); font-weight: 800; font-size: 24px; line-height: 1.1; }

/* Hero intro paragraph */
.lede { font-size: 20px; line-height: 1.55; max-width: 600px; text-wrap: pretty; }

/* Section intro paragraph */
.lead { font-size: 19px; line-height: 1.6; text-wrap: pretty; }

.body-lg { font-size: 17px; line-height: 1.6; }
.body    { font-size: 16px; line-height: 1.5; }
.small   { font-size: 15px; font-weight: 500; }
.label   { font-weight: 700; font-size: 14px; }
.label-sm { font-weight: 700; font-size: 13px; }
.text-pink { color: var(--c-pink-text); }
.text-muted { color: var(--c-muted); }

/* The yellow highlighter behind a word in a heading: Let's <span class="hl">talk.</span> */
.hl { background: var(--c-yellow); padding: 0 12px; border-radius: 18px; }
.hl--cream { background: var(--c-cream); }
.hl--pink { background: var(--c-pink); }

/* Underlined inline link with an arrow badge */
.link { font-weight: 700; font-size: 17px; text-decoration: underline; }


/* ==========================================================================
   5. Components
   ========================================================================== */

/* ---------- Buttons ----------
   White pill, thick coloured border and a solid shadow of the same colour.
   Drops 4px into its shadow on hover and 6px on press (Brand Guide §6).

   <a class="btn" href="/contact">Let's talk</a>              pink (default)
   <a class="btn btn--teal" href="#form">Request a quote</a>
   <a class="btn btn--ink" href="/contact">Let's talk</a>
   Sizes: btn--sm (header), default, btn--lg, btn--compact (cookie banner).
   Wrap a row of buttons in .btn-row so the shadow is not clipped. */
.btn {
    --btn: var(--c-pink);
    display: inline-block;
    background: var(--c-white);
    color: var(--c-ink-deep);
    border: 3px solid var(--btn);
    box-shadow: 0 6px 0 var(--btn);
    padding: 13px 24px;
    border-radius: var(--r-pill);
    font-family: inherit;
    font-weight: 700;
    font-size: 16px;
    text-decoration: none;
    cursor: pointer;
    transition: transform .08s, box-shadow .08s;
}
.btn:hover {
    background: var(--c-cream);
    color: var(--c-ink-deep);
    transform: translateY(4px);
    box-shadow: 0 2px 0 var(--btn);
}
.btn:active { transform: translateY(6px); box-shadow: 0 0 0 var(--btn); }

.btn--teal { --btn: var(--c-teal); }
.btn--ink  { --btn: var(--c-ink); }
.btn--yellow { --btn: var(--c-yellow); }

.btn--sm { padding: 12px 22px; font-size: 15px; }
.btn--lg { padding: 15px 28px; font-size: 17px; }

.btn--compact { padding: 10px 18px; font-size: 15px; box-shadow: 0 5px 0 var(--btn); }
.btn--compact:hover { transform: translateY(3px); box-shadow: 0 2px 0 var(--btn); }
.btn--compact:active { transform: translateY(5px); box-shadow: 0 0 0 var(--btn); }

/* A button that ends in the arrow badge */
.btn--arrow { display: inline-flex; align-items: center; line-height: 1; }
.btn--arrow .arrow { margin-left: 10px; vertical-align: 0; flex: none; }

.btn[disabled], .btn[aria-disabled="true"] { opacity: .6; cursor: default; pointer-events: none; }

.btn-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; padding-bottom: 6px; }
.btn-pad { padding-bottom: 6px; }

/* Round icon button (close ×) */
.close-btn {
    width: 36px; height: 36px; border-radius: 50%;
    background: var(--c-white); border: 3px solid var(--c-ink); box-shadow: 0 3px 0 var(--c-ink);
    color: var(--c-ink); font-family: inherit; font-size: 20px; font-weight: 800; line-height: 1;
    cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
    transition: transform .08s, box-shadow .08s;
}
.close-btn:hover { transform: translateY(2px); box-shadow: 0 1px 0 var(--c-ink); }
.close-btn:active { transform: translateY(3px); box-shadow: 0 0 0 var(--c-ink); }

/* ---------- Arrow badge ----------
   <?= $view->partial('partials/arrow') ?> at the end of a link or button.
   Slides right and turns teal when the parent is hovered. */
.arrow {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; margin-left: 8px; vertical-align: -6px;
    border-radius: 50%; background: var(--c-yellow); border: 2px solid var(--c-ink);
    transition: transform .25s var(--ease-spring), background .2s;
}
.arrow svg { display: block; }
.arrow path { fill: none; stroke: var(--c-ink); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
a:hover .arrow, button:hover .arrow { transform: translateX(4px); background: var(--c-teal); }

/* ---------- Chips / tags ----------
   <span class="chip tint-teal">Live</span> */
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
    background: var(--tint, var(--c-white));
    padding: 5px 14px; border-radius: var(--r-pill);
    font-weight: 700; font-size: 13px; border: 2px solid var(--c-ink);
}
.chip--cream { background: var(--c-cream); }
.chip--plain { border: 0; }

/* Larger outlined link pill (404 "Popular places") */
.pill-link {
    padding: 10px 18px; border-radius: var(--r-pill); border: 3px solid var(--c-ink);
    background: var(--c-white); font-weight: 700; font-size: 16px;
}
.pill-link:hover { background: var(--c-lilac-tint); color: var(--c-ink); }

/* ---------- Cards ----------
   <div class="card tint-yellow"><span class="label">Phone</span>…</div>
   .card--outline is the white card with a 2px ink border. */
.card { border-radius: var(--r-card); padding: 24px; display: flex; flex-direction: column; gap: 8px; }
.card--outline { background: var(--c-white); border: 2px solid var(--c-ink); gap: 12px; }
.card--bordered { border: 3px solid var(--c-ink); }
.card--32 { border-radius: 32px; padding: 32px; }

/* Card lift on hover: [data-lift] / [data-lift-soft] in the prototypes */
.lift { transition: transform .25s var(--ease-spring), box-shadow .25s; }
.lift:hover { transform: translateY(-6px) rotate(-.4deg); box-shadow: var(--sh-ink); }
.lift-soft { transition: transform .25s var(--ease-spring); }
.lift-soft:hover { transform: translateY(-6px); }

/* ---------- Coloured dot (menu items, lists) ---------- */
.dot { flex: none; width: 14px; height: 14px; margin-top: 5px; border-radius: 5px 5px 5px 1px; }
.dot--pink   { background: var(--c-pink); }
.dot--teal   { background: var(--c-teal); }
.dot--yellow { background: var(--c-yellow); }
.dot--lilac  { background: var(--c-lilac); }
.dot--orange { background: var(--c-orange); }

/* ---------- Number badge (Brand Guide §5) ----------
   <span class="num-badge bg-teal">1</span>, optional .num-badge--tail */
.num-badge {
    position: relative; width: 52px; height: 46px; border-radius: 16px;
    border: 3px solid var(--c-ink); display: flex; align-items: center; justify-content: center;
    font-family: var(--f-display); font-weight: 800; font-size: 22px; transform: rotate(-4deg);
}

/* ---------- Hero panel ----------
   <section class="hero" id="main" tabindex="-1">
     <div class="hero__panel">
       <div class="blob blob--pink blob--corner" data-float aria-hidden="true"></div>
       <h1 class="h1">Let's <span class="hl">talk.</span></h1>
       <p class="lede">…</p>
     </div>
   </section> */
.hero { padding: 16px var(--gutter) 0; }
.hero:focus { outline: none; }
.hero__panel {
    background: var(--c-teal); color: var(--c-ink);
    border-radius: var(--r-hero);
    padding: clamp(36px, 6vw, 80px);
    display: flex; flex-direction: column; gap: 20px;
    position: relative; overflow: hidden;
}
.hero__panel > :not(.blob) { position: relative; }
.hero__panel--center { align-items: center; text-align: center; gap: 24px; }
/* A chip or label above a hero heading keeps its own width. */
.hero__panel > .chip, .hero__panel > .err-chip { align-self: flex-start; }
.hero__panel--center > .chip, .hero__panel--center > .err-chip { align-self: center; }

/* ---------- Floating blobs ----------
   Decorative circles that drift and bounce inside their positioned parent
   (motion.js moves anything with data-float). Give each one a colour and a
   size/position class; page CSS defines one-off positions. */
.blob { position: absolute; border-radius: 50%; pointer-events: none; }
.blob--pink   { background: var(--c-pink); }
.blob--yellow { background: var(--c-yellow); }
.blob--teal   { background: var(--c-teal); }
.blob--lilac  { background: var(--c-lilac); }
.blob--orange { background: var(--c-orange); }
.blob--cream  { background: var(--c-cream); }
/* The big one in the top-right corner of most heroes */
.blob--corner { right: -90px; top: -90px; width: 240px; height: 240px; }

/* ---------- Speech bubbles ----------
   Simple: <div class="say tint-pink">Hi there!</div>
   Outlined with a tail (the contact form's success message):
   <div class="bubble"><div class="bubble__body">…</div>
     <span class="bubble__tail" aria-hidden="true"></span>
     <span class="bubble__tail-in" aria-hidden="true"></span></div> */
.say { border-radius: 28px 28px 28px 6px; padding: 18px 22px; font-weight: 600; font-size: 17px; }

.bubble { position: relative; align-self: flex-start; margin-bottom: 28px; }
.bubble__body {
    background: var(--c-cream); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink);
    border-radius: 36px 36px 36px 0; padding: 28px 32px;
    display: flex; flex-direction: column; gap: 10px;
}
.bubble__tail, .bubble__tail-in {
    position: absolute; top: calc(100% - 3px); clip-path: polygon(0 0, 100% 0, 0 100%);
}
.bubble__tail { left: 0; width: 40px; height: 30px; background: var(--c-ink); }
.bubble__tail-in { left: 3px; width: 26px; height: 20px; background: var(--c-cream); }

/* ---------- Forms ----------
   <label class="field">Your name<input class="field__input" name="name"></label>
   Pink offset shadow on focus. */
.field { display: flex; flex-direction: column; gap: 6px; font-weight: 600; font-size: 15px; }
.field__input {
    width: 100%;
    border: 2px solid var(--c-ink); border-radius: var(--r-field);
    padding: 14px 16px; font-size: 16px; font-weight: 400;
    background: var(--c-white); color: var(--c-ink); font-family: inherit;
    transition: box-shadow .15s, border-color .15s;
}
.field__input:focus { border-color: var(--c-pink); box-shadow: 0 4px 0 var(--c-pink); outline: none; }
textarea.field__input { resize: vertical; }
.field__input[aria-invalid="true"] { border-color: var(--c-pink-text); }
.field__error { color: var(--c-pink-text); font-size: 14px; font-weight: 700; }

.field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); gap: 16px; }

.form-alert {
    border-radius: var(--r-field); padding: 12px 16px; font-weight: 600; font-size: 15px; line-height: 1.45;
    border: 2px solid var(--c-ink);
}
.form-alert--error { background: var(--c-pink-tint); }
.form-alert--success { background: var(--c-teal-tint); }

/* Spam honeypot: off-screen, not display:none (some bots skip hidden fields). */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Dashed "value goes here" chip from the prototypes — dev placeholders only */
.ph-value {
    align-self: flex-start; border: 2px dashed var(--c-ink); border-radius: 12px; padding: 4px 10px;
    font-family: var(--f-mono); font-size: 14px; font-weight: 500;
}

/* ---------- Image placeholder ----------
   A stand-in for a screenshot we do not have yet, styled like the design's
   empty image slots. <?= $view->partial('partials/img-placeholder', ['caption' => 'TheatreHQ screenshot']) ?>
   It fills its parent; put it inside .frame-shot (or anything sized). */
.img-ph {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; width: 100%; height: 100%; padding: 12px; text-align: center;
    color: var(--c-ink); background: rgba(127, 127, 127, .08);
    font: 500 13px/1.3 system-ui, -apple-system, sans-serif; letter-spacing: .01em;
    border-radius: inherit;
}
.img-ph::after {
    content: ''; position: absolute; inset: 0; border: 1.5px dashed currentColor; opacity: .35;
    border-radius: inherit; pointer-events: none;
}
.img-ph__icon { opacity: .45; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.img-ph__cap { max-width: 90%; opacity: .75; }
.img-ph--16-10 { height: auto; aspect-ratio: 16 / 10; }
.img-ph--4-3   { height: auto; aspect-ratio: 4 / 3; }
.img-ph--3-2   { height: auto; aspect-ratio: 3 / 2; }
.img-ph--1-1   { height: auto; aspect-ratio: 1 / 1; }

/* A framed screenshot: rounded, ink border, 16:10 */
.frame-shot {
    width: 100%; aspect-ratio: 16 / 10; border-radius: var(--r-shot); border: 2px solid var(--c-ink);
    overflow: hidden; background: var(--c-cream); display: block;
}
img.frame-shot { aspect-ratio: auto; object-fit: cover; }

/* A screenshot drawn as a browser window: thin ink outline, small corners and
   a lilac title bar with three dots. Sized from the viewport, so the bar and
   corners stay in proportion on a phone. Doubled class (and body) to beat the
   rounded "card" radii each page's own frame rules give the same element. */
body .screen-frame.screen-frame {
    --bar: clamp(12px, 1.7vw, 24px);
    --dot: clamp(5px, .62vw, 9px);
    --edge: clamp(2px, .22vw, 3px);
    position: relative; overflow: hidden;
    padding-top: var(--bar); background: var(--c-cream);
    border: var(--edge) solid var(--c-ink);
    border-radius: clamp(6px, .9vw, 14px);
}
.screen-frame::before {
    content: ""; position: absolute; z-index: 1; top: 0; left: 0; right: 0; height: var(--bar);
    border-bottom: var(--edge) solid var(--c-ink); box-sizing: border-box;
    background:
        radial-gradient(circle closest-side, var(--c-pink) 92%, transparent) calc(var(--dot) * 1.2) 50% / var(--dot) var(--dot) no-repeat,
        radial-gradient(circle closest-side, var(--c-yellow) 92%, transparent) calc(var(--dot) * 2.7) 50% / var(--dot) var(--dot) no-repeat,
        radial-gradient(circle closest-side, var(--c-teal) 92%, transparent) calc(var(--dot) * 4.2) 50% / var(--dot) var(--dot) no-repeat,
        var(--c-lilac-tint);
}
body .screen-frame.screen-frame > img { border: 0; border-radius: 0; object-position: top; }

/* Brand Guide "image cut-out": striped stand-in for decorative imagery */
.cutout {
    width: 100%; aspect-ratio: 4 / 3; border-radius: 40px 40px 40px 10px; border: 3px solid var(--c-ink);
    background: repeating-linear-gradient(135deg, var(--c-teal-tint) 0 10px, #b8eef0 10px 20px);
}

/* ---------- FAQ (details/summary) ----------
   <details class="faq tint-yellow"><summary class="faq__q"><span class="faq__title">…</span>
   <span class="faq__icon" aria-hidden="true">+</span></summary><p class="faq__a">…</p></details> */
.faq { border-radius: 24px; padding: 20px 24px; }
.faq__q {
    cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__title { font-family: var(--f-display); font-weight: 800; font-size: 21px; line-height: 1.25; }
.faq__icon {
    flex: none; width: 44px; height: 44px; border-radius: 50%; background: var(--c-white);
    border: 3px solid var(--c-ink); box-shadow: 0 4px 0 var(--c-ink);
    display: flex; align-items: center; justify-content: center;
    font-family: var(--f-display); font-weight: 800; font-size: 26px; line-height: 1; padding-bottom: 3px;
    transition: transform .25s var(--ease-spring), box-shadow .1s, background .2s;
}
.faq__q:hover .faq__icon { transform: translateY(2px); box-shadow: 0 1px 0 var(--c-ink); }
.faq[open] > .faq__q .faq__icon { transform: rotate(45deg); background: var(--c-teal); }
.faq[open] > .faq__q:hover .faq__icon { transform: rotate(45deg) translateY(2px); }
.faq__a { margin: 12px 0 0; font-size: 17px; line-height: 1.6; text-wrap: pretty; }

/* ---------- Toggle switch ---------- */
.switch {
    flex: none; width: 56px; height: 32px; border-radius: var(--r-pill); border: 3px solid var(--c-ink);
    background: var(--c-switch-off); cursor: pointer; padding: 0;
    display: flex; align-items: center; justify-content: flex-start;
}
.switch[aria-checked="true"] { background: var(--c-teal); justify-content: flex-end; }
.switch__knob { width: 20px; height: 20px; margin: 0 3px; border-radius: 50%; background: var(--c-white); border: 2px solid var(--c-ink); }


/* ==========================================================================
   6. Shell
   ========================================================================== */

/* ---------- Skip link ---------- */
.skip-link {
    position: absolute; left: -9999px; top: 12px; z-index: 100;
    background: var(--c-white); color: var(--c-ink); border: 3px solid var(--c-ink);
    border-radius: var(--r-pill); padding: 10px 18px; font-weight: 700;
}
.skip-link:focus { left: 12px; }

/* ---------- Header ---------- */
.site-header {
    position: relative; z-index: 40;
    padding: 20px var(--gutter);
    display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
}

.brand { display: flex; align-items: center; gap: 12px; }
.brand:hover { color: var(--c-ink); }

.wordmark {
    font-family: var(--f-display); font-weight: 800; font-size: 24px;
    letter-spacing: -0.6px; line-height: 0.9;
}
.wordmark__light { font-weight: 500; }
.wordmark--footer { font-size: 28px; }

/* The logo wobbles once on load and again on hover; the roof bobs with it. */
@keyframes hdWobble  { 0% { transform: none; } 20% { transform: rotate(-9deg) scale(1.08); } 40% { transform: rotate(6deg) scale(1.04); } 60% { transform: rotate(-3deg); } 80% { transform: rotate(1deg); } 100% { transform: none; } }
@keyframes hdWobble2 { 0% { transform: none; } 20% { transform: rotate(-9deg) scale(1.08); } 40% { transform: rotate(6deg) scale(1.04); } 60% { transform: rotate(-3deg); } 80% { transform: rotate(1deg); } 100% { transform: none; } }
@keyframes hdBob  { 0%, 100% { transform: none; } 30% { transform: translateY(-3px); } 60% { transform: translateY(1px); } }
@keyframes hdBob2 { 0%, 100% { transform: none; } 30% { transform: translateY(-3px); } 60% { transform: translateY(1px); } }

.logo-mark { display: block; flex: none; }
.logo-mark--animated { transform-origin: 25% 100%; animation: hdWobble .9s .4s both; }
a:hover .logo-mark--animated { animation: hdWobble2 .9s both; }
.logo-mark--animated .logo-mark__roof { animation: hdBob .9s .4s both; }
a:hover .logo-mark--animated .logo-mark__roof { animation: hdBob2 .9s both; }
.logo-mark--footer { width: 34px; height: 38px; }

/* ---------- Desktop nav ---------- */
.nav {
    display: flex; align-items: center; gap: clamp(14px, 2vw, 28px); flex-wrap: wrap;
    font-weight: 600; font-size: 16px;
}

.nav__btn {
    background: none; border: 0; padding: 0; font: inherit; font-weight: 600; font-size: 16px;
    color: var(--c-ink); cursor: pointer; display: flex; align-items: center; gap: 6px;
}
.nav__btn:hover, .nav__btn.is-current, .nav__link.is-current { color: var(--c-pink-text); }

.caret {
    width: 22px; height: 22px; border-radius: 50%; background: var(--c-yellow);
    display: inline-flex; align-items: center; justify-content: center;
    transition: transform .25s var(--ease-spring), background .2s;
}
.caret svg { display: block; margin-top: 1px; }
.caret path { fill: none; stroke: var(--c-ink); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
button:hover .caret { background: var(--c-teal); }
button[aria-expanded="true"] .caret { transform: rotate(180deg); background: var(--c-teal); }

.site-header__cta { display: flex; align-items: center; gap: 16px; }

/* ---------- Mega-menus ----------
   .mm wraps a button and its panel. ui.js opens it (.is-open) on hover,
   click and keyboard, and sets the panel's left/width so it stays on screen
   (placeMenu() in the prototype). Without JS, :hover / :focus-within open it. */
.mm { position: relative; }

.mm__pos {
    display: none;
    position: absolute; top: 100%; left: 0;
    padding-top: 16px; z-index: 60;
    width: 640px; max-width: calc(100vw - 40px);
}
.mm__pos--720 { width: 720px; }

.mm.is-open > .mm__pos { display: block; }
html:not(.js) .mm:hover > .mm__pos,
html:not(.js) .mm:focus-within > .mm__pos { display: block; left: -24px; }

.mm__box {
    background: var(--c-white); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink);
    border-radius: 28px; padding: 16px;
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 8px;
}
.mm__box--products { grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 12px; }
.mm__box--cases { gap: 12px; }

.mm__col { display: flex; flex-direction: column; gap: 2px; }
.mm__cards { display: flex; flex-direction: column; gap: 10px; }

.mm__heading { font-weight: 700; font-size: 13px; color: var(--c-pink-text); padding: 6px 14px; }

.mm__link { display: flex; gap: 14px; align-items: flex-start; padding: 12px 14px; border-radius: var(--r-item); }
.mm__link:hover { color: var(--c-ink); }
.mm__link.hover-pink:hover   { background: var(--c-pink-tint); }
.mm__link.hover-yellow:hover { background: var(--c-yellow-tint); }
.mm__link.hover-teal:hover   { background: var(--c-teal-tint); }
.mm__link.hover-lilac:hover  { background: var(--c-lilac-tint); }
.mm__link.hover-orange:hover { background: var(--c-orange-tint); }
.mm__link.hover-cream:hover  { background: var(--c-cream); }

.mm__text { display: flex; flex-direction: column; gap: 2px; }
.mm__title-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.mm__label { font-weight: 700; font-size: 16px; }
.mm__desc { font-weight: 500; font-size: 14px; line-height: 1.4; color: var(--c-muted); }
.mm__badge { font-weight: 700; font-size: 11px; background: var(--c-line); padding: 2px 8px; border-radius: var(--r-pill); }

.mm__all {
    grid-column: 1 / -1; border-top: 2px solid var(--c-line);
    padding: 12px 14px 4px; font-weight: 700; font-size: 15px;
}

/* Product preview card (Products menu). Its tint class is swapped by ui.js. */
.pv {
    border-radius: var(--r-bubble); padding: 18px;
    display: flex; flex-direction: column; gap: 10px;
    transition: background .2s;
}
.pv:hover { color: var(--c-ink); }
.pv__label { font-weight: 700; font-size: 13px; color: var(--c-ink); }
.pv__title { font-family: var(--f-display); font-weight: 800; font-size: 24px; line-height: 1.05; }
.pv__img { width: 100%; border-radius: var(--r-shot); border: 2px solid var(--c-ink); display: block; }
.pv__media {
    width: 100%; height: auto; aspect-ratio: 16 / 10; border-radius: var(--r-shot);
    border: 2px solid var(--c-ink); overflow: hidden;
}
.pv__media.img-ph { background: var(--c-cream); }
.pv__media.img-ph::after { border-radius: 12px; }
.pv__soon {
    display: flex; align-items: center; justify-content: center;
    background: repeating-linear-gradient(135deg, var(--c-cream) 0 12px, var(--tint) 12px 24px);
}
.pv__soon-pill {
    background: var(--c-white); border: 2px solid var(--c-ink); padding: 5px 14px;
    border-radius: var(--r-pill); font-weight: 700; font-size: 13px;
}
.pv__link { font-weight: 700; font-size: 15px; }

/* Case-study cards (Case studies menu; reusable elsewhere) */
.case-card { border-radius: var(--r-bubble); padding: 18px; display: flex; flex-direction: column; gap: 10px; }
.case-card:hover { color: var(--c-ink); }
.case-card--featured { background: var(--c-yellow-tint); }
.case-card--featured:hover { background: var(--c-yellow-tint-hover); }
.case-card--small { background: var(--c-teal-tint); padding: 14px 18px; gap: 6px; }
.case-card--small:hover { background: var(--c-teal-tint-hover); }
.case-card__label { font-weight: 700; font-size: 13px; }
.case-card__title { font-family: var(--f-display); font-weight: 800; font-size: 24px; line-height: 1.05; }
.case-card--small .case-card__title { font-size: 19px; line-height: 1.1; }
.case-card__desc { font-size: 14px; line-height: 1.45; font-weight: 500; }
.case-card__link { font-weight: 700; font-size: 15px; }

/* ---------- Burger + mobile nav (below 1150px) ---------- */
.burger {
    width: 52px; height: 52px; border-radius: 50%;
    background: var(--c-white); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink-xs);
    cursor: pointer; display: none; align-items: center; justify-content: center; padding: 0;
    transition: transform .08s, box-shadow .08s;
}
.burger:hover { transform: translateY(3px); box-shadow: 0 2px 0 var(--c-ink); }
.burger:active { transform: translateY(5px); box-shadow: 0 0 0 var(--c-ink); }
.burger__bars { display: flex; flex-direction: column; gap: 5px; }
.burger__bars span { display: block; width: 22px; height: 3px; border-radius: 2px; background: var(--c-ink); }
.burger__bars span:last-child { width: 14px; background: var(--c-pink); }
.burger__x { display: none; font-size: 26px; font-weight: 800; line-height: 1; color: var(--c-ink); }
.burger[aria-expanded="true"] .burger__bars { display: none; }
.burger[aria-expanded="true"] .burger__x { display: block; }

.mobile-nav {
    flex-basis: 100%;
    background: var(--c-white); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink);
    border-radius: 28px; padding: 16px;
    display: flex; flex-direction: column; gap: 14px;
}
.mobile-nav__cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 8px; }
.mobile-nav__col { display: flex; flex-direction: column; }
.mobile-nav__heading { padding: 6px 12px; }
.mobile-nav__link { padding: 10px 12px; border-radius: 14px; font-weight: 600; font-size: 17px; }
.mobile-nav__link:hover { background: var(--c-cream); color: var(--c-ink); }
.mobile-nav__link--sub { padding: 8px 12px 8px 24px; font-size: 16px; }
.mobile-nav__feature {
    margin: 4px 0; padding: 10px 12px; border-radius: 16px 16px 16px 4px;
    font-weight: 700; font-size: 17px; background: var(--c-yellow); border: 3px solid var(--c-ink);
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.mobile-nav__feature:hover { background: var(--c-yellow-hover); color: var(--c-ink); }
.mobile-nav__chip {
    background: var(--c-cream); border: 2px solid var(--c-ink); border-radius: var(--r-pill);
    padding: 2px 10px; font-size: 12px; font-weight: 700;
}
.mobile-nav__cta { align-self: flex-start; margin-bottom: 6px; }

@media (max-width: 1149.98px) {
    .nav, .site-header__cta { display: none; }
    .burger { display: flex; }
}
@media (min-width: 1150px) {
    .mobile-nav { display: none !important; }
}

/* ---------- Skyline (the houses the footer sits on) ---------- */
.skyline { margin-top: 112px; margin-bottom: -3px; line-height: 0; position: relative; z-index: 1; }
.skyline__svg { display: block; overflow: visible; max-width: none; }
.skyline path, .skyline__ground { fill: var(--c-ink); }
.skyline__ground { pointer-events: none; }
.skyline g { cursor: default; }
.skyline g rect { transition: fill .15s; }
.skyline .w-teal   { fill: var(--c-teal); }
.skyline .w-yellow { fill: var(--c-yellow); }
.skyline .w-pink   { fill: var(--c-pink); }
.skyline .w-lilac  { fill: var(--c-lilac); }
.skyline g:hover rect { fill: var(--c-ink-night); }

/* ---------- Footer ---------- */
.site-footer {
    background: var(--c-ink); color: var(--c-cream);
    padding: 56px var(--gutter) 40px;
    display: flex; flex-direction: column; gap: 40px;
}
.site-footer a { color: var(--c-cream); }
.site-footer a:hover { color: var(--c-yellow); }
.site-footer__top { display: flex; justify-content: space-between; gap: 40px; flex-wrap: wrap; }
.site-footer__brand { display: flex; flex-direction: column; gap: 12px; max-width: 320px; }
.site-footer__logo { display: flex; align-items: center; gap: 12px; }
.site-footer__blurb { font-size: 16px; line-height: 1.5; }
.site-footer__cols { display: flex; gap: 56px; flex-wrap: wrap; font-size: 16px; }
.site-footer__col { display: flex; flex-direction: column; gap: 10px; }
.site-footer__heading { font-weight: 800; font-family: var(--f-display); font-size: 19px; color: var(--c-yellow); }
.site-footer__legal { border-top: 2px solid var(--c-cream); padding-top: 20px; font-size: 14px; }

/* ---------- Cookie banner ---------- */
.cookie {
    position: fixed; left: clamp(12px, 3vw, 32px); bottom: clamp(12px, 3vw, 32px); z-index: 80;
    width: min(440px, calc(100vw - 24px));
    background: var(--c-white); color: var(--c-ink);
    border: 3px solid var(--c-ink); box-shadow: var(--sh-ink);
    border-radius: 32px 32px 32px 8px; padding: 24px;
    display: flex; flex-direction: column; gap: 14px;
}
.cookie__head { display: flex; align-items: center; gap: 12px; }
.cookie__icon { width: 40px; height: 40px; flex: none; border-radius: 50%; background: var(--c-yellow); position: relative; display: block; }
.cookie__icon span { position: absolute; border-radius: 50%; background: var(--c-ink); }
.cookie__icon span:nth-child(1) { width: 7px; height: 7px; left: 10px; top: 11px; }
.cookie__icon span:nth-child(2) { width: 6px; height: 6px; left: 23px; top: 20px; }
.cookie__icon span:nth-child(3) { width: 5px; height: 5px; left: 13px; top: 25px; }
.cookie__title { font-family: var(--f-display); font-weight: 800; font-size: 24px; line-height: 1; }
.cookie__text { font-size: 15px; line-height: 1.5; }
.cookie__text a { font-weight: 700; text-decoration: underline; color: var(--c-ink); }
.cookie__actions { display: flex; gap: 10px; flex-wrap: wrap; padding-bottom: 6px; }
.cookie__manage {
    cursor: pointer; font-family: inherit; background: none; border: 0; padding: 10px 6px;
    font-weight: 700; font-size: 15px; color: var(--c-ink); text-decoration: underline;
}
.cookie__manage:hover { color: var(--c-pink-text); }

@media (max-width: 600px) {
    .cookie { left: 8px; right: 8px; bottom: 8px; width: auto; padding: 16px; gap: 10px; box-shadow: var(--sh-ink-xs); }
    .cookie__icon { display: none; }
    .cookie__text { font-size: 14px; }
    .cookie__title { font-size: 20px; }
}

.cookie-prefs {
    position: fixed; inset: 0; z-index: 90; background: var(--c-overlay);
    display: flex; align-items: center; justify-content: center; padding: 16px;
}
.cookie-prefs__dialog {
    width: min(560px, 100%); max-height: calc(100vh - 32px); overflow: auto;
    background: var(--c-cream); color: var(--c-ink);
    border: 3px solid var(--c-ink); box-shadow: 0 10px 0 var(--c-ink);
    border-radius: var(--r-dialog); padding: clamp(20px, 4vw, 32px);
    display: flex; flex-direction: column; gap: 16px; position: relative;
}
.cookie-prefs__dialog:focus { outline: none; }
.cookie-prefs__close { position: absolute; top: 16px; right: 16px; }
.cookie-prefs__title { font-family: var(--f-display); font-weight: 800; font-size: 30px; line-height: 1; padding-right: 48px; }
.cookie-prefs__intro { font-size: 15px; line-height: 1.5; }
.cookie-prefs__row { border-radius: 22px; padding: 18px; display: flex; gap: 16px; align-items: flex-start; justify-content: space-between; }
.cookie-prefs__copy { display: flex; flex-direction: column; gap: 4px; }
.cookie-prefs__name { font-weight: 700; font-size: 16px; }
.cookie-prefs__desc { font-size: 14px; line-height: 1.45; }
.cookie-prefs__always { flex: none; font-weight: 700; font-size: 13px; background: var(--c-white); padding: 6px 12px; border-radius: var(--r-pill); }
.cookie-prefs__actions { display: flex; gap: 10px; flex-wrap: wrap; padding-bottom: 6px; }
.cookie-prefs__actions .btn--compact { padding: 11px 20px; }

/* ---------- WhatsApp float ---------- */
.wa-float {
    position: fixed; right: clamp(16px, 3vw, 32px); bottom: clamp(16px, 3vw, 32px); z-index: 50;
    display: flex; flex-direction: column; align-items: flex-end; gap: 14px; pointer-events: none;
}
.wa-float__bubble { position: relative; pointer-events: auto; }
/* Arriving (ui.js): the typing indicator first, then the message pops in. */
.wa-float__typing {
    display: none; align-items: center; gap: 6px;
    padding: 14px 18px;
    background: var(--c-white);
    border: 3px solid var(--c-pink); box-shadow: 0 6px 0 var(--c-pink);
    border-radius: 24px;
    animation: hdChatIn .35s var(--ease-pop) both;
    transform-origin: 100% 100%;
}
.wa-float__typing i {
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--c-ink); opacity: .35;
    animation: hdChatDot 1s ease-in-out infinite;
}
.wa-float__typing i:nth-child(2) { animation-delay: .15s; }
.wa-float__typing i:nth-child(3) { animation-delay: .3s; }
.wa-float__bubble.is-typing .wa-float__typing { display: inline-flex; }
.wa-float__bubble.is-typing .wa-float__msg,
.wa-float__bubble.is-typing .wa-float__close { display: none; }
/* The whole bubble pops, close button included, so the two never part company mid-animation. */
.wa-float__bubble.is-said { animation: hdChatIn .5s var(--ease-pop) both; transform-origin: 100% 100%; }
.wa-float__msg {
    background: var(--c-white); color: var(--c-ink-deep);
    border: 3px solid var(--c-pink); box-shadow: 0 6px 0 var(--c-pink);
    border-radius: 24px; padding: 14px 18px; max-width: 240px;
    font-size: 15px; line-height: 1.4; font-weight: 500;
    display: flex; flex-direction: column; gap: 2px;
    transition: transform .08s, box-shadow .08s;
}
.wa-float__msg:hover { color: var(--c-ink-deep); transform: translateY(4px); box-shadow: 0 2px 0 var(--c-pink); }
.wa-float__hello { font-family: var(--f-display); font-weight: 800; font-size: 18px; }
/* Centred on the curve of the bubble's top-right corner, not on its square
   corner: the 24px radius bends the border ~8px in from each edge at 45°, so
   a 32px button sits at -8px/-8px and the border passes evenly behind it on
   both sides. */
.wa-float__close {
    position: absolute; top: -8px; right: -8px; width: 32px; height: 32px; border-radius: 50%;
    background: var(--c-white); border: 3px solid var(--c-ink); box-shadow: 0 3px 0 var(--c-ink);
    color: var(--c-ink); font-family: inherit; font-size: 18px; font-weight: 800; line-height: 1;
    cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
    transition: transform .08s, box-shadow .08s;
}
.wa-float__close:hover { transform: translateY(2px); box-shadow: 0 1px 0 var(--c-ink); }
.wa-float__close:active { transform: translateY(3px); box-shadow: 0 0 0 var(--c-ink); }
.wa-float__btn {
    pointer-events: auto; width: 64px; height: 64px; border-radius: 50%;
    background: var(--c-whatsapp); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink-sm);
    display: flex; align-items: center; justify-content: center;
    transition: transform .08s, box-shadow .08s;
}
.wa-float__btn svg { fill: var(--c-white); }
.wa-float__btn:hover { transform: translateY(4px); box-shadow: 0 2px 0 var(--c-ink); }
.wa-float__btn:active { transform: translateY(6px); box-shadow: 0 0 0 var(--c-ink); }

/* ---------- Back to top (added by motion.js) ---------- */
.to-top {
    position: fixed; right: calc(clamp(16px, 3vw, 32px) + 6px); bottom: 112px; z-index: 69;
    width: 52px; height: 52px; border-radius: 50%;
    background: var(--c-yellow); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink-xs);
    cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
    opacity: 0; transform: translateY(16px) scale(.8); pointer-events: none;
    transition: opacity .25s, transform .3s var(--ease-spring), box-shadow .08s;
}
.to-top path { fill: none; stroke: var(--c-ink); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.to-top.is-shown { opacity: 1; transform: none; pointer-events: auto; }
.to-top.is-shown:hover { box-shadow: 0 2px 0 var(--c-ink); transform: translateY(3px); }
/* motion.js appends the button to <body>, outside .page, hence body:has().
   No WhatsApp float on the page: sit in the corner itself. */
body:not(:has(.wa-float)) .to-top { right: clamp(16px, 3vw, 32px); bottom: clamp(16px, 3vw, 32px); }
/* The "Hello there!" bubble is showing above the WhatsApp button, where this
   would otherwise sit on top of it: move alongside the button instead. Once
   the bubble is dismissed it goes back above the button. */
body:has(.wa-float__bubble:not([hidden])) .to-top {
    right: calc(clamp(16px, 3vw, 32px) + 80px);
    bottom: calc(clamp(16px, 3vw, 32px) + 6px);
}

/* ---------- Reading progress (articles: add data-reading to the article) ---------- */
.reading-bar {
    position: fixed; left: 0; top: 0; height: 6px; width: 100%; z-index: 100;
    background: linear-gradient(90deg, var(--c-teal), var(--c-yellow), var(--c-pink));
    transform-origin: 0 50%; transform: scaleX(0); border-radius: 0 3px 3px 0;
}

/* ---------- "Copied!" tip for Copy link buttons ---------- */
.copy-tip {
    position: absolute; left: 50%; bottom: calc(100% + 12px); transform: translateX(-50%) scale(.6);
    background: var(--c-yellow); color: var(--c-ink); border: 3px solid var(--c-ink);
    border-radius: 16px 16px 16px 4px; padding: 6px 12px; font-weight: 800; font-size: 14px;
    white-space: nowrap; opacity: 0; pointer-events: none;
    transition: transform .3s cubic-bezier(.34, 1.8, .5, 1), opacity .2s;
}
.copy-tip.is-shown { opacity: 1; transform: translateX(-50%) scale(1); }
.has-tip { position: relative; }

/* ---------- December snow on the skyline (motion.js) ---------- */
@keyframes hdFlake { 0% { transform: translate(0, -20px); } 100% { transform: translate(var(--dx), var(--dy)); } }
.snow { position: absolute; left: 0; right: 0; overflow: hidden; pointer-events: none; z-index: 2; }
.snow__flake { position: absolute; top: 0; border-radius: 50%; background: var(--c-cream); animation: hdFlake 12s linear infinite; }
.skyline__snow { fill: none; stroke: var(--c-cream); stroke-width: 7; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; }

/* ---------- Flash toast (site photo replacement) ---------- */
.toast {
    position: fixed; top: 16px; left: 50%; transform: translateX(-50%); z-index: 95; margin: 0;
    background: var(--c-teal-tint); border: 3px solid var(--c-ink); box-shadow: var(--sh-ink-xs);
    border-radius: var(--r-field); padding: 12px 18px; font-weight: 700;
}
.toast--error { background: var(--c-pink-tint); }

/* Reduced motion: no wobble, no floating, no springs. motion.js also checks. */
@media (prefers-reduced-motion: reduce) {
    .logo-mark--animated, .logo-mark--animated * { animation: none !important; }
    .snow { display: none; }
    *, *::before, *::after { scroll-behavior: auto !important; }
}


/* ==========================================================================
   7. Shared pages
   ========================================================================== */

/* ---------- Enquiry form: card, paper-plane send, success bubble ----------
   Shared by /contact, the home page's short form and the "Let's talk" pop-up;
   driven by /assets/js/enquiry.js. */
.enquiry {
    background: var(--c-cream);
    border-radius: var(--r-card);
    padding: 24px;
    display: flex; flex-direction: column; gap: 16px;
}

.enquiry__send { padding-bottom: 6px; }
.enquiry__note { font-size: 14px; font-weight: 500; }

/* "Sending…" with the paper plane flying off */
@keyframes hdPlane {
    0%   { transform: translate(0, 0) rotate(0); }
    15%  { transform: translate(-10px, 6px) rotate(8deg); }
    100% { transform: translate(520px, -260px) rotate(-18deg) scale(.6); opacity: 0; }
}
@keyframes hdFade { 0% { opacity: 0; } 30% { opacity: 1; } }
@keyframes hdPop {
    0%   { opacity: 0; transform: scale(.6) translateY(20px); }
    100% { opacity: 1; transform: none; }
}

.plane { position: relative; height: 58px; width: 200px; }
.plane__text {
    position: absolute; left: 0; top: 6px; padding: 12px 0;
    font-weight: 700; font-size: 16px;
    animation: hdFade .9s ease both;
}
.plane__svg {
    position: absolute; left: 110px; top: 4px; overflow: visible;
    animation: hdPlane 1.1s cubic-bezier(.5, 0, .75, 0) both;
}
.plane__body { fill: var(--c-white); stroke: var(--c-ink); stroke-width: 4; stroke-linejoin: round; }
.plane__fold { fill: var(--c-yellow); stroke: var(--c-ink); stroke-width: 4; stroke-linejoin: round; }

/* The success bubble */
.enquiry-done:focus { outline: none; }
.enquiry-done--pop { animation: hdPop .6s var(--ease-pop) both; }
.enquiry-done__title {
    font-family: var(--f-display); font-weight: 800;
    font-size: clamp(28px, 3vw, 38px); line-height: 1.05;
}
.enquiry-done__text { font-size: 17px; line-height: 1.5; }

@media (prefers-reduced-motion: reduce) {
    .plane__text, .plane__svg, .enquiry-done--pop { animation: none; }
    .plane__svg { display: none; }
}

/* ---------- "Let's talk" pop-up (partials/talk-dialog.php) ----------
   A native <dialog>: the yellow form panel from /contact, lifted onto a
   chunky ink frame that pops in like the success bubble. The dialog itself
   has no padding so that a click whose target is the <dialog> element can
   only be the backdrop (ui.js closes on it); .talk__body fills the box and
   scrolls when the form is taller than the screen. */
.talk {
    width: min(640px, calc(100% - 32px)); max-width: none;
    max-height: calc(100dvh - 32px);
    margin: auto; padding: 0;
    background: var(--c-yellow); color: var(--c-ink);
    border: 3px solid var(--c-ink); border-radius: var(--r-panel);
    box-shadow: var(--sh-ink);
    overflow: hidden;
}
.talk[open] { display: flex; flex-direction: column; animation: hdTalkPop .45s var(--ease-pop) both; }
.talk::backdrop { background: var(--c-overlay); animation: hdTalkFade .25s ease both; }
@keyframes hdTalkPop {
    0%   { opacity: 0; transform: scale(.88) translateY(24px); }
    100% { opacity: 1; transform: none; }
}
@keyframes hdTalkFade { 0% { opacity: 0; } 100% { opacity: 1; } }

.talk__blob   { right: -70px; top: -70px; width: 180px; height: 180px; }
.talk__blob-2 { left: -44px; bottom: -44px; width: 110px; height: 110px; }

.talk__body {
    position: relative; z-index: 1;
    overflow-y: auto; overscroll-behavior: contain;
    max-height: calc(100dvh - 38px);
    padding: clamp(24px, 4vw, 40px);
    display: flex; flex-direction: column; gap: 16px;
}
.talk__title {
    margin: 0; padding-right: 56px;
    font-family: var(--f-display); font-weight: 800;
    font-size: clamp(40px, 5vw, 56px); line-height: .95; letter-spacing: -0.03em;
}
.talk__lead { margin: 0 0 4px; max-width: 480px; font-size: 17px; line-height: 1.5; }

/* The WhatsApp bubble's round × , a size up so it is an easy target. */
.talk__close {
    position: absolute; z-index: 2; top: 18px; right: 18px;
    width: 44px; height: 44px; border-radius: 50%; padding: 0;
    background: var(--c-white); color: var(--c-ink);
    border: 3px solid var(--c-ink); box-shadow: 0 4px 0 var(--c-ink);
    font-family: inherit; font-size: 26px; font-weight: 800; line-height: 1;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: transform .08s, box-shadow .08s;
}
.talk__close:hover  { transform: translateY(2px); box-shadow: 0 2px 0 var(--c-ink); }
.talk__close:active { transform: translateY(4px); box-shadow: 0 0 0 var(--c-ink); }

/* Nothing behind the pop-up scrolls while it is open. */
html.is-talking { overflow: hidden; }

@media (max-width: 600px) {
    .talk { width: calc(100% - 16px); max-height: calc(100dvh - 16px); border-radius: var(--r-card); box-shadow: var(--sh-ink-xs); }
    .talk__body { max-height: calc(100dvh - 22px); }
    .talk__close { top: 14px; right: 14px; }
}

@media (prefers-reduced-motion: reduce) {
    .talk[open], .talk::backdrop { animation: none; }
}

/* ---------- Looping art, paused off screen (motion.js) ----------
   Case-study animations ([data-anim]) and the service pages' scenes
   ([data-pause-offscreen]) loop forever; motion.js marks them .is-offscreen
   while scrolled out of view, so they cost nothing there. */
.is-offscreen, .is-offscreen * { animation-play-state: paused !important; }

/* ---------- Chat entrance for speech-bubble lists (assets/js/chat.js) ----------
   A list marked data-chat arrives like a conversation. A pending bubble keeps
   its space and its text — transparent rather than visibility:hidden or
   display:none, either of which would also take the words away from screen
   readers until the animation reached them. Its typing indicator sits where
   the message will appear; chat.js copies the bubble's colour and corners
   onto it (before the bubble goes transparent) and adds .chat-right to
   bubbles pushed in from the left. */
.is-chat > li { position: relative; transform-origin: 0 100%; }
.is-chat > li.chat-right { transform-origin: 100% 100%; }
.is-chat > li.chat-pending {
    color: transparent;
    background: transparent !important;
    border-color: transparent;
    box-shadow: none;
}

.chat-typing {
    position: absolute; top: 0; left: 0;
    display: none; align-items: center; gap: 6px;
    padding: 16px 20px;
    background: var(--c-cream); border-radius: 24px 24px 24px 6px;
    animation: hdChatIn .35s var(--ease-pop) both;
}
.chat-right > .chat-typing { left: auto; right: 0; }
.chat-typing-now > .chat-typing { display: inline-flex; }

.chat-typing i {
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--c-ink); opacity: .35;
    animation: hdChatDot 1s ease-in-out infinite;
}
.chat-typing i:nth-child(2) { animation-delay: .15s; }
.chat-typing i:nth-child(3) { animation-delay: .3s; }

.is-chat > li.chat-said { animation: hdChatIn .5s var(--ease-pop) both; }

@keyframes hdChatIn {
    0%   { opacity: 0; transform: translateY(14px) scale(.6); }
    100% { opacity: 1; transform: none; }
}
@keyframes hdChatDot {
    0%, 60%, 100% { transform: none; opacity: .35; }
    30%           { transform: translateY(-5px); opacity: 1; }
}

/* ---------- Error pages ---------- */
.err-num {
    font-family: var(--f-display); font-weight: 800; font-size: clamp(120px, 22vw, 280px);
    line-height: .8; letter-spacing: -0.04em;
}
.err-chip { background: var(--c-cream); padding: 5px 14px; border-radius: var(--r-pill); border: 2px solid var(--c-ink); font-weight: 700; font-size: 13px; }

/* ---------- Prose (policies, articles until they get their own CSS) ---------- */
.prose { font-size: 18px; line-height: 1.7; max-width: 760px; }
.prose > * + * { margin-top: 1em; }
.prose h2 { font-family: var(--f-display); font-weight: 800; font-size: clamp(26px, 3vw, 34px); line-height: 1.1; margin-top: 1.6em; }
.prose h3 { font-family: var(--f-display); font-weight: 800; font-size: 22px; line-height: 1.2; margin-top: 1.4em; }
.prose a { text-decoration: underline; font-weight: 600; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose code { font-family: var(--f-mono); font-size: .9em; }


/* ==========================================================================
   8. Shared page blocks (added with Home / About / Pricing)
   Patterns that recur across most of the .dc.html prototypes. Reuse these
   rather than re-declaring them in page CSS.
   ========================================================================== */

/* ---------- Announcement bar (above the header; layout renders it when a
   controller passes $announce = ['text' => …, 'link' => …, 'href' => …]) ---------- */
.announce {
    background: var(--c-yellow); padding: 12px 24px;
    display: flex; justify-content: center; gap: 12px; flex-wrap: wrap;
    font-weight: 600; font-size: 15px; text-align: center;
}
.announce__link { text-decoration: underline; }

/* ---------- Inner-page hero copy (About, Pricing, Products, Case studies, …) ----------
   Inside .hero__panel: <span class="page-hero__kicker">Pricing</span>
   <h1 class="page-hero__title">Honest <span class="hl">pricing.</span></h1>
   <p class="page-hero__text">…</p>. .blob--hero-2 is the small second blob. */
.page-hero__kicker { font-weight: 700; font-size: 16px; }
.page-hero__title {
    font-family: var(--f-display); font-weight: 800;
    font-size: clamp(44px, 6.5vw, 88px); line-height: .95; letter-spacing: -0.03em;
    max-width: 1000px; text-wrap: balance;
}
.page-hero__text { font-size: 20px; line-height: 1.55; max-width: 660px; text-wrap: pretty; }
.blob--hero-2 { right: 140px; bottom: -60px; width: 120px; height: 120px; }

/* ---------- Section heading with a small coloured kicker above it ----------
   <div class="sec-head"><span class="sec-head__kicker">Always included</span>
   <h2 class="h2 sec-head__title">Every project, every time.</h2></div> */
.sec-head { display: flex; flex-direction: column; gap: 16px; }
.sec-head__kicker { font-weight: 700; font-size: 15px; color: var(--c-pink-text); }
.sec-head__kicker--ink { color: var(--c-ink); }
.sec-head__title { max-width: 820px; text-wrap: balance; }
.sec-head__text { font-size: 19px; line-height: 1.6; max-width: 760px; text-wrap: pretty; }

/* ---------- Tinted split panel: copy on the left, a list or image on the right ---------- */
.split-panel {
    border-radius: var(--r-hero); padding: clamp(28px, 5vw, 64px);
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
    gap: 40px; align-items: start;
}
.split-panel__copy { display: flex; flex-direction: column; gap: 18px; }
.split-panel__text { font-size: 18px; line-height: 1.6; max-width: 760px; text-wrap: pretty; }

/* ---------- Three-up card grid: thirds when there is room, else 260px min ---------- */
.grid-thirds {
    display: grid; gap: 20px;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, max(260px, calc(33.3% - 22px))), 1fr));
}

/* Rounded tinted card with one squared corner (feature / promise cards) */
.feature-card {
    border-radius: 32px 32px 32px 8px; padding: 28px;
    display: flex; flex-direction: column; gap: 12px;
}
.feature-card__title { font-family: var(--f-display); font-weight: 800; font-size: 26px; line-height: 1.1; }
.feature-card__text { font-size: 17px; line-height: 1.55; }

/* ---------- Numbered list in cream bubbles, with a tilted badge ----------
   <ol class="badge-list"><li class="badge-row">
     <span class="badge-num bg-teal" aria-hidden="true">1</span>
     <span class="badge-row__text">…</span></li></ol>
   Odd badges tilt left, even ones right; both spring the other way on hover. */
.badge-list { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 0; list-style: none; }
.badge-row {
    background: var(--c-cream); border-radius: 24px 24px 24px 6px; padding: 16px 20px 16px 16px;
    display: flex; gap: 16px; align-items: center;
}
.badge-row__text { font-size: 17px; line-height: 1.5; font-weight: 500; }
.badge-num {
    flex: none; position: relative; width: 52px; height: 46px; border-radius: 16px;
    border: 3px solid var(--c-ink); display: flex; align-items: center; justify-content: center;
    font-family: var(--f-display); font-weight: 800; font-size: 24px; line-height: 1; color: var(--c-ink);
    padding-top: 2px; transform: rotate(-4deg); cursor: default;
    transition: transform .35s cubic-bezier(.34, 1.8, .5, 1);
}
/* The little speech tail: an ink triangle with a fill-coloured one inside it. */
.badge-num::before, .badge-num::after {
    content: ''; position: absolute; top: calc(100% - 3px); clip-path: polygon(0 0, 100% 0, 0 100%);
}
.badge-num::before { left: 7px; width: 18px; height: 15px; background: var(--c-ink); }
.badge-num::after { left: 10px; width: 10px; height: 8px; background: inherit; }
.badge-row:nth-child(even) .badge-num { transform: rotate(3deg); }
.badge-row:hover .badge-num { transform: rotate(5deg) scale(1.1) translateY(-3px); }
.badge-row:nth-child(even):hover .badge-num { transform: rotate(-5deg) scale(1.1) translateY(-3px); }

/* ---------- Closing yellow CTA panel with a speech-bubble tail ----------
   <section class="section cta-section">
     <div class="cta-panel">
       <div class="blob blob--teal blob--cta" data-float aria-hidden="true"></div>
       <h2 class="cta-panel__title">…</h2><p class="cta-panel__text">…</p>
       <div class="btn-row">…</div>
     </div>
     <span class="cta-tail" data-tail aria-hidden="true"></span>
   </section>
   data-tail lets motion.js mirror the blob into the tail. */
.cta-section { position: relative; }
.cta-panel {
    background: var(--c-yellow); border-radius: 48px 48px 48px 0; padding: clamp(36px, 6vw, 72px);
    display: flex; flex-direction: column; gap: 20px; align-items: flex-start;
    position: relative; overflow: hidden;
}
.cta-panel > :not(.blob) { position: relative; }
.cta-panel__title {
    font-family: var(--f-display); font-weight: 800; font-size: clamp(36px, 5vw, 64px);
    line-height: 1; letter-spacing: -0.025em; max-width: 820px;
}
.cta-panel__text { font-size: 20px; line-height: 1.55; max-width: 600px; }
.blob--cta { right: -60px; bottom: -80px; width: 220px; height: 220px; }
.cta-tail {
    position: absolute; left: var(--gutter); bottom: -30px; width: 60px; height: 32px;
    overflow: hidden; background: var(--c-yellow); clip-path: polygon(0 0, 100% 0, 0 100%);
}

@media (prefers-reduced-motion: reduce) {
    .badge-num { transition: none; }
}
