/*
Theme Name: kuvaria
Theme URI:
Author: Räikee Oy
Author URI:
Description: A modern agency starter theme built with block editor patterns and theme.json.
Version: 1.0.63
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: kuvaria
Tags: block-patterns, block-styles, full-site-editing, wide-blocks
*/

/* ==========================================================================
   Layer Declarations
   ========================================================================== */

/*
   Cascade layers ensure predictable specificity. Layers are applied in order:

   1. reset     — Browser resets + box-sizing normalization (in this file)
   2. wpglobal  — WordPress global styles (auto-wrapped via functions.php for cascade control)
   3. base      — Global element defaults (in this file)
   4. tokens    — Design system tokens via CSS custom properties (in this file)
   5. header    — Header/navigation styles (see assets/css/header.css)
   6. components — Reusable component styles (see styles/blocks/core/*.css)
   7. utilities — Helper & utility classes (in this file)
   8. overrides — High-specificity client overrides (add your custom CSS here)

   Note: reset, base, tokens, and utilities are defined in this file.
   wpglobal layer wraps WP's global-styles-inline-css to make it overridable by other layers.
   header styles live in assets/css/header.css (enqueued via functions.php).
   Block-specific CSS lives in styles/blocks/core/ (auto-enqueued via functions.php).
*/

/* Layer order is also declared early in functions.php (wp_head priority 1) to ensure
   wpglobal is positioned correctly before WordPress outputs global-styles-inline-css.
   If you change this order, update functions.php to match.

   wpglobal is the @layer wrapper for WP's global-styles-inline-css (see functions.php
   wp_print_styles hook). Because it's named and positioned early, any layer declared
   after it (base → overrides) can override WP layout rules — including .is-layout-flow
   blockGap margins — without !important. */
@layer reset, wpglobal, base, tokens, header, components, utilities, overrides;

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

@layer reset {
  /* 1. Use a more-intuitive box-sizing model + 2. Remove default margin */
  * {
    box-sizing: border-box;

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

    &:not(dialog) {
      margin: 0;
    }
  }

  /* 3. Enable keyword animations + 4. Accessible line-height + 5. Text rendering */
  html {
    @media (prefers-reduced-motion: no-preference) {
      interpolate-size: allow-keywords;
    }
  }

  body {
    line-height: var(--wp--custom--line-height--normal, 1.5);
    -webkit-font-smoothing: antialiased;
  }

  /* 6. Improve media defaults */
  :is(img, picture, video, canvas, svg) {
    display: block;
    max-inline-size: 100%;
  }

  /* 7. Inherit fonts for form controls */
  :is(input, button, textarea, select) {
    font: inherit;
  }

  /* 8. Avoid text overflows + 9. Improve line wrapping */
  :is(p, h1, h2, h3, h4, h5, h6) {
    overflow-wrap: break-word;
  }

  p {
    text-wrap: pretty;
    /* Finnish body copy: auto syllabification where the browser has the fi dict,
       stacked with hand-rolled &shy; seams in content for no-dict browsers
       (Chrome on Windows/Android). Headings stay manual (below).
       See feedback_finnish_hyphenation. */
    hyphens: auto;
  }

  :is(h1, h2, h3, h4, h5, h6) {
    text-wrap: balance;
    /* Headings never auto-hyphenate — avoids ugly mid-compound display breaks. */
    hyphens: manual;
  }

  /* 10. Create a root stacking context */
  :is(#root, #__next) {
    isolation: isolate;
  }
}

/* ==========================================================================
   Base
   ========================================================================== */

@layer base {
  :where(a) {
    color: inherit;
  }

  :where(ul, ol) {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body {
    background-color: var(--wp--preset--color--base);
    color: var(--wp--preset--color--contrast);
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    line-height: 1.65;
  }

  h1, h2, h3, h4, h5, h6 {
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 400;
    letter-spacing: -0.005em;
    line-height: 1.05;
  }

  a {
    color: inherit;
  }

  /* Flow/constrained layout spacing — override wpglobal blockGap defaults.
     WP applies margin-block-start to ALL layout children (both .is-layout-flow and
     .is-layout-constrained). We restore spacing only for content-level elements so
     container blocks (group, cover, columns, template-part) stay at 0.

     Covers both block editor classes (.wp-block-*) and plain HTML elements —
     post content outputs bare <p>/<blockquote> etc. with no block class.
     Excludes :first-child to avoid unwanted top margin at the start of a container. */
  :is(.is-layout-flow, .is-layout-constrained)
    > :where(
      p,
      h1,
      h2,
      h3,
      h4,
      h5,
      h6,
      blockquote,
      ul,
      ol,
      figure,
      hr,
      .wp-block-paragraph,
      .wp-block-heading,
      .wp-block-list,
      .wp-block-quote,
      .wp-block-pullquote,
      .wp-block-image,
      .wp-block-gallery,
      .wp-block-buttons,
      .wp-block-table,
      .wp-block-separator
    ):not(:first-child) {
    margin-block-start: var(--wp--preset--spacing--40);
  }

  /* Skip link — visible on focus only */
  .skip-link {
    position: absolute;
    inset-inline-start: -9999px;
    z-index: var(--wp--custom--z-index--toast, 400);
    padding-block: 0.5em;
    padding-inline: 1em;
    background: var(--wp--preset--color--contrast, #0f172a);
    color: var(--wp--preset--color--base, #fff);
    text-decoration: none;
    font-weight: 700;

    &:focus {
      inset-inline-start: 0;
      inset-block-start: 0;
    }
  }
}

/* ==========================================================================
   Tokens — Derived colors & semantic aliases via CSS Relative Colors (RCS)
   All values here are derived from theme.json palette entries using oklch()
   relative color syntax. Swapping hex values in theme.json auto-propagates.
   ========================================================================== */

/*
   QUICK REFERENCE — CSS Custom Properties (All Sources)
   ================================================

   COLOR PALETTE (from theme.json)
   —— Preset colors (use in blocks):
   --wp--preset--color--{primary, accent, secondary, base, contrast, subtle, muted}

   —— Derived states (hover, active, subtle, alpha scales):
   --color-{primary,accent,secondary}-hover           (lighten +15%)
   --color-{primary,accent,secondary}-active          (darken -15%)
   --color-{primary,accent}-subtle                    (light tint, 50% alpha)
   --color-{primary,accent,base,contrast}-alpha-{10,20,50,80}  (transparency scales)

   —— Status colors (contextual messages):
   --color-{success,warning,error,info}              (main color)
   --color-{success,warning,error,info}-subtle       (light variant)

   SEMANTIC SURFACES
   --color-surface                 (card backgrounds)
   --color-surface-raised          (slightly elevated)
   --color-surface-overlay         (semi-transparent overlay)
   --color-surface-sunken          (indented area)
   --color-surface-scrim           (semi-transparent dark layer)

   BORDERS & FOCUS
   --color-border                  (subtle dividers)
   --color-border-strong           (prominent dividers)
   --color-border-interactive      (interactive elements)
   --focus-ring                    (2px solid primary color)
   --focus-ring-offset             (2px)

   Z-INDEX (from theme.json — keep minimal)
   --wp--custom--z-index--sticky   (200 — header)
   --wp--custom--z-index--dropdown (300 — menus)
   --wp--custom--z-index--overlay  (250 — overlays)
   --wp--custom--z-index--modal    (300 — modals)
   --wp--custom--z-index--toast    (400 — notifications)

   TRANSITIONS (from theme.json — use timing + easing separately for flexibility)
   --wp--custom--transition--fast  (150ms ease — shorthand, use for simple transitions)
   --wp--custom--transition--normal (300ms ease — shorthand, use for simple transitions)
   --wp--custom--transition--slow  (500ms ease — shorthand, use for simple transitions)

   TIMING (compose with easing for complex multi-property transitions)
   --wp--custom--timing--fast      (150ms)
   --wp--custom--timing--normal    (300ms)
   --wp--custom--timing--slow      (500ms)

   EASING (use with timing for granular control)
   --wp--custom--easing--standard  (ease — standard, smooth)
   --wp--custom--easing--in        (ease-in — slow start)
   --wp--custom--easing--out       (ease-out — slow end)
   --wp--custom--easing--inOut     (cubic-bezier custom — smooth both ends)

   TYPOGRAPHY (from theme.json)
   --wp--preset--font-family--{heading, body}
   --wp--preset--font-size--{small, medium, large, x-large, 2x-large, 3x-large, 4x-large}
   --wp--custom--line-height--{tight, normal, relaxed}
   --wp--custom--letter-spacing--{tight, normal, wide}

   SPACING (from theme.json, increments 10–100)
   --wp--preset--spacing--{10, 20, 30, 40, 50, 60, 70, 80, 90, 100}

   SHADOWS (from theme.json)
   --wp--preset--shadow--{sm, md, lg, xl, inner}

   BORDER RADIUS (from theme.json)
   --wp--preset--border--radius--{small, medium, large, full}

   LAYOUT (from theme.json)
   --wp--style--global--content-size  (800px — main content width)
   --wp--style--global--wide-size     (1200px — wide section width)

   Note: WordPress preset variables are auto-generated from theme.json.
   Custom theme variables (--wp--custom--*) are defined in theme.json settings.custom.
*/

@layer tokens {
  :root {
    /* ----- Primary: hover / active / subtle ----- */
    --color-primary-hover: oklch(
      from var(--wp--preset--color--primary) calc(l + 0.15) c h
    );
    --color-primary-active: oklch(
      from var(--wp--preset--color--primary) calc(l - 0.15) c h
    );
    --color-primary-subtle: oklch(
      from var(--wp--preset--color--primary) calc(l + 0.45) c h / 0.5
    );

    /* ----- Accent: hover / active / subtle ----- */
    --color-accent-hover: oklch(
      from var(--wp--preset--color--accent) calc(l + 0.15) c h
    );
    --color-accent-active: oklch(
      from var(--wp--preset--color--accent) calc(l - 0.15) c h
    );
    --color-accent-subtle: oklch(
      from var(--wp--preset--color--accent) calc(l + 0.45) c h / 0.5
    );

    /* ----- Secondary: hover ----- */
    --color-secondary-hover: oklch(
      from var(--wp--preset--color--secondary) calc(l + 0.15) c h
    );

    /* ----- Primary: transparency scale ----- */
    --color-primary-alpha-10: oklch(
      from var(--wp--preset--color--primary) l c h / 0.1
    );
    --color-primary-alpha-20: oklch(
      from var(--wp--preset--color--primary) l c h / 0.2
    );
    --color-primary-alpha-50: oklch(
      from var(--wp--preset--color--primary) l c h / 0.5
    );

    /* ----- Accent: transparency scale ----- */
    --color-accent-alpha-10: oklch(
      from var(--wp--preset--color--accent) l c h / 0.1
    );
    --color-accent-alpha-20: oklch(
      from var(--wp--preset--color--accent) l c h / 0.2
    );
    --color-accent-alpha-50: oklch(
      from var(--wp--preset--color--accent) l c h / 0.5
    );

    /* ----- Contrast: transparency scale (overlays, borders, scrims) ----- */
    --color-contrast-alpha-5: oklch(
      from var(--wp--preset--color--contrast) l c h / 0.05
    );
    --color-contrast-alpha-10: oklch(
      from var(--wp--preset--color--contrast) l c h / 0.1
    );
    --color-contrast-alpha-20: oklch(
      from var(--wp--preset--color--contrast) l c h / 0.2
    );
    --color-contrast-alpha-50: oklch(
      from var(--wp--preset--color--contrast) l c h / 0.5
    );
    --color-contrast-alpha-80: oklch(
      from var(--wp--preset--color--contrast) l c h / 0.8
    );

    /* ----- Base: transparency scale (light overlays on dark bgs) ----- */
    --color-base-alpha-10: oklch(
      from var(--wp--preset--color--base) l c h / 0.1
    );
    --color-base-alpha-20: oklch(
      from var(--wp--preset--color--base) l c h / 0.2
    );
    --color-base-alpha-50: oklch(
      from var(--wp--preset--color--base) l c h / 0.5
    );

    /* ----- Semantic: surfaces ----- */
    --color-surface: var(--wp--preset--color--base);
    --color-surface-raised: var(--wp--preset--color--subtle);
    --color-surface-overlay: oklch(
      from var(--wp--preset--color--contrast) calc(l - 0.02) c h / 0.97
    );
    --color-surface-sunken: oklch(
      from var(--wp--preset--color--contrast) calc(l - 0.04) c h / 0.94
    );
    --color-surface-scrim: var(--color-contrast-alpha-50);

    /* ----- Semantic: borders ----- */
    --color-border: var(--color-contrast-alpha-10);
    --color-border-strong: var(--color-contrast-alpha-20);
    --color-border-interactive: var(--wp--preset--color--primary);
    --color-border-focus: var(--wp--preset--color--primary);

    /* ----- Semantic: focus ring ----- */
    --color-focus-ring: var(--wp--preset--color--primary);
    --focus-ring: 2px solid var(--color-focus-ring);
    --focus-ring-offset: 2px;

    /* ----- Status: hex fallbacks (overridden to OKLCH below) ----- */
    --color-success: #16a34a;
    --color-warning: #ca8a04;
    --color-error: #dc2626;
    --color-info: #2563eb;
  }

  /* OKLCH enhancement for status colors + derive subtle variants via relative colors */
  @supports (color: oklch(0% 0 0)) {
    :root {
      --color-success: oklch(55% 0.18 150);
      --color-success-subtle: oklch(
        from var(--color-success) calc(l + 0.42) c h
      );
      --color-warning: oklch(70% 0.16 85);
      --color-warning-subtle: oklch(
        from var(--color-warning) calc(l + 0.27) c h
      );
      --color-error: oklch(55% 0.22 28);
      --color-error-subtle: oklch(from var(--color-error) calc(l + 0.42) c h);
      --color-info: oklch(55% 0.2 260);
      --color-info-subtle: oklch(from var(--color-info) calc(l + 0.42) c h);
    }
  }
}

/* ==========================================================================
   Header
   Header & navigation styles live in assets/css/header.css (native block
   header: wp:site-title wordmark + core wp:navigation). That file is enqueued
   after this one so its unlayered nav rules can beat core's unlayered
   Navigation CSS without !important. See feedback_wp_native_nav_branding.md.
   ========================================================================== */

/* ==========================================================================
   Components
   ========================================================================== */

@layer components {
  /* Component styles are added per-task below */

  /* Landing portal — Wave variant
     Bottom 35% of each column is a solid colored cap (primary / secondary / accent).
     A single SVG with three clipped path copies sits on the seam between image and
     caps, so the irregular wave flows continuously from one color to the next. */
  /* Section fills 100vh exactly for the immersive effect. Grid has two rows:
     row 1 (photo) is 1fr — fills whatever's left after the cap. Row 2 (cap)
     is auto, sized to max of cap content and cap min-block-size. Cap's
     min-block-size is bumped to ~50vh below so the photo is shorter (cap
     takes a bigger share of viewport, photo gets cropped from the bottom). */
  .kuvaria-landing-waves {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr auto;
    min-height: 100vh;
    overflow: hidden;
    background: #111;
    isolation: isolate;
  }

  .kuvaria-landing-waves__masthead {
    position: absolute;
    top: clamp(24px, 4vh, 48px);
    inset-inline-start: 50%;
    translate: -50% 0;
    z-index: 10;
    width: min(300px, 42%);
    pointer-events: none;
  }

  .kuvaria-landing-waves__masthead img { inline-size: 100%; block-size: auto; display: block; }

  /* No isolation: isolate — sublogo's z-index inside the cap needs to
     escape to the section's stacking context to sit above the wave.
     Subgrid inherits the section's grid-template-rows so cap below
     drops into the section's auto-sized row 2 alongside the others.
     No min-block-size — column sizes to its grid rows now. */
  .kuvaria-landing-waves__col {
    position: relative;
    overflow: hidden;
    cursor: pointer;
    color: var(--wp--preset--color--base);
    text-decoration: none;
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / -1;
  }

  .kuvaria-landing-waves__col--1 { grid-column: 1; }
  .kuvaria-landing-waves__col--2 { grid-column: 2; }
  .kuvaria-landing-waves__col--3 { grid-column: 3; }

  /* Photo fills the whole column, cover-cropped; the opaque cap covers the
     lower portion, so the visible photo is the band above the cap. The width
     is pinned (inline-size 106%) and the height is pinned by anchoring BOTH
     block edges (-3% top and bottom) — not a width-driven square — so the
     photo always reaches the cap and the section background never shows
     through as a gap at narrow widths. background-position: center keeps the
     subject centered in the cover crop. The 3% bleed on every side gives the
     zoom/rotate room to breathe without exposing the column edge. */
  .kuvaria-landing-waves__col::before {
    content: "";
    position: absolute;
    inset-inline-start: -3%;
    inset-block-start: -3%;
    inset-block-end: -3%;
    inline-size: 106%;
    background-size: cover;
    background-position: center;
    transition: transform 900ms cubic-bezier(.2, .6, .2, 1);
    z-index: -2;
  }

  /* Background photo per column. Editable via the landing-portal block: render.php
     sets --kuvaria-col-bg inline when a photo is chosen; otherwise these defaults
     apply (cols 1 & 2 swapped per client direction). */
  .kuvaria-landing-waves__col--1::before { background-image: var(--kuvaria-col-bg, url('assets/images/landing-col-2.jpg')); }
  .kuvaria-landing-waves__col--2::before { background-image: var(--kuvaria-col-bg, url('assets/images/landing-col-1.jpg')); }
  .kuvaria-landing-waves__col--3::before { background-image: var(--kuvaria-col-bg, url('assets/images/kuvaria-kuva.jpg')); }

  .kuvaria-landing-waves__col:hover::before,
  .kuvaria-landing-waves__col:focus-visible::before { transform: scale(1.08) rotate(-1.5deg); }

  @media (prefers-reduced-motion: reduce) {
    .kuvaria-landing-waves__col::before { transition: none; }
    .kuvaria-landing-waves__col:hover::before,
    .kuvaria-landing-waves__col:focus-visible::before { transform: none; }
  }


  /* Cap sits in section's row 2 (via column's subgrid). All caps share that
     row's height, which auto-sizes to the tallest cap content (col 1, which
     carries the sublogo) OR to min-block-size — whichever is bigger.
     min-block-size pushed to ~50vh so the cap dominates more of the viewport
     and the photo above is shorter. overflow: visible lets the wave SVG
     render above the cap top edge. */
  .kuvaria-landing-waves__cap {
    grid-row: 2;
    position: relative;
    z-index: 1;
    min-block-size: clamp(200px, 26vh, 360px);
    padding: clamp(12px, 1.4vw, 20px) clamp(24px, 3vw, 40px) clamp(32px, 4vw, 56px);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    overflow: visible;
  }

  .kuvaria-landing-waves__col--1 .kuvaria-landing-waves__cap { background: var(--wp--preset--color--secondary); }
  .kuvaria-landing-waves__col--2 .kuvaria-landing-waves__cap { background: var(--wp--preset--color--primary); }
  .kuvaria-landing-waves__col--3 .kuvaria-landing-waves__cap { background: var(--wp--preset--color--accent); }

  /* Sublogo sits inside the cap above the body (matches original landing
     portal placement). z-index: 2 puts it above the wave (z: 1) so when
     content overflows the cap upward on short viewports, the logo stays
     visible on top of the wave instead of being clipped by it. Requires
     column to NOT have its own stacking context — see column rule above. */
  .kuvaria-landing-waves__sublogo {
    position: relative;
    z-index: 2;
    align-self: flex-start;
    margin-block-end: clamp(14px, 2vw, 22px);
  }

  .kuvaria-landing-waves__sublogo img { inline-size: clamp(56px, 6vw, 80px); block-size: auto; display: block; }
  .kuvaria-landing-waves__col--2 .kuvaria-landing-waves__sublogo img,
  .kuvaria-landing-waves__col--3 .kuvaria-landing-waves__sublogo img { inline-size: clamp(110px, 14vw, 180px); }

  /* Waveline — one SVG per cap, each 300% wide so the same path geometry
     spans the full row. Per-column inset offsets shift each SVG so it
     starts at the section's left edge — the column's overflow:hidden
     then crops to the column's third. Same path, three colors, perfect
     mathematical continuity at column boundaries with no clipPath needed. */
  .kuvaria-landing-waves__waveline {
    position: absolute;
    top: 0;
    /* WordPress (or a block library default) ships `svg { max-width: 100% }`
       which would clamp this to the cap's width — explicitly unset it so
       the waveline can actually span the full row. */
    width: 100vw;
    max-width: none;
    height: clamp(28px, 4vw, 80px);
    /* Sit just above cap top, with 1px overlap downward into cap. */
    transform: translateY(calc(-100% + 1px));
    z-index: 1;
    display: block;
    pointer-events: none;
  }

  /* Each cap's SVG starts at the section's left edge so the path renders
     identically across all three; column overflow:hidden crops to the
     column's slice. -100% / -200% are relative to cap width (= col width). */
  .kuvaria-landing-waves__col--1 .kuvaria-landing-waves__waveline { left: 0; }
  .kuvaria-landing-waves__col--2 .kuvaria-landing-waves__waveline { left: -100%; }
  .kuvaria-landing-waves__col--3 .kuvaria-landing-waves__waveline { left: -200%; }

  .kuvaria-landing-waves__title {
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 400;
    font-size: clamp(28px, 3.6vw, 56px);
    line-height: 1;
    letter-spacing: -0.005em;
    margin: 0 0 clamp(12px, 1.4vw, 18px);
    color: var(--wp--preset--color--base);
    hyphens: manual;
    text-wrap: balance;
    overflow-wrap: break-word;
  }

  .kuvaria-landing-waves__lede {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: clamp(13px, 1vw, 15px);
    line-height: 1.55;
    margin: 0 0 clamp(16px, 2vw, 24px);
    max-width: 36ch;
    color: var(--wp--preset--color--base);
    opacity: 0.95;
  }

  .kuvaria-landing-waves__cta {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 400;
    font-size: 13px;
    letter-spacing: 0.04em;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    align-self: flex-start;
    border-block-end: 1px solid color-mix(in oklch, var(--wp--preset--color--base) 70%, transparent);
    padding-block-end: 4px;
    color: var(--wp--preset--color--base);
  }

  .kuvaria-landing-waves__cta span { transition: translate 300ms ease; }

  .kuvaria-landing-waves__col:hover .kuvaria-landing-waves__cta span,
  .kuvaria-landing-waves__col:focus-visible .kuvaria-landing-waves__cta span { translate: 6px 0; }

  /* Pink cap (col 1) — ink-brown body text, orange title */
  .kuvaria-landing-waves__col--1 .kuvaria-landing-waves__lede,
  .kuvaria-landing-waves__col--1 .kuvaria-landing-waves__cta {
    color: var(--wp--preset--color--contrast);
  }

  .kuvaria-landing-waves__col--1 .kuvaria-landing-waves__title {
    color: var(--wp--preset--color--accent);
  }

  .kuvaria-landing-waves__col--1 .kuvaria-landing-waves__cta {
    border-block-end-color: color-mix(in oklch, var(--wp--preset--color--contrast) 60%, transparent);
  }

  /* Stack on narrow viewports — drop grid entirely. Each cap keeps its own
     wave; full-width caps make the curve read better than at 1/3 width. */
  @media (max-width: 768px) {
    .kuvaria-landing-waves {
      display: block;
      min-height: auto;
    }

    .kuvaria-landing-waves__col {
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      min-block-size: 70vh;
      grid-row: auto;
      grid-column: auto;
    }

    .kuvaria-landing-waves__cap {
      grid-row: auto;
      min-block-size: 0;
    }

    /* Full-width columns — reset SVG offset so wave is visible on all columns */
    .kuvaria-landing-waves__col--2 .kuvaria-landing-waves__waveline,
    .kuvaria-landing-waves__col--3 .kuvaria-landing-waves__waveline { left: 0; }

    .kuvaria-landing-waves__masthead { top: 20px; width: min(280px, 70%); }
  }


  /* ── Hero for /kivijalkaliike — bespoke 2-column marketing hero ──────────
     Editable core/columns (className kuvaria-hero-v2): text left, a real
     client-editable image block right. Was raw wp:html; the treatment below
     now targets the block output. The image fill lives in the unlayered escape
     hatch (core's figure margin + img height:auto are unlayered — see
     feedback_wp_layer_trap). Stacks on mobile via WP core's column default. */
  .kuvaria-hero-v2.wp-block-columns {
    max-inline-size: var(--wp--style--global--wide-size, 1440px);
    margin-inline: auto;
    margin-block: 0;
    gap: 0;
    align-items: stretch;
    min-block-size: 480px;
    background: var(--wp--preset--color--base);
  }

  .kuvaria-hero-v2__text {
    padding-block: clamp(48px, 8vw, 96px);
    padding-inline: clamp(28px, 5vw, 72px);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .kuvaria-hero-v2__eyebrow {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 500;
    font-size: 11px;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--wp--preset--color--accent);
    margin: 0 0 22px;
  }

  /* Non-italic per client rule — the old green italic <em> second line is gone. */
  .kuvaria-hero-v2__title {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(40px, 6vw, 72px);
    line-height: 1;
    letter-spacing: -0.015em;
    margin: 0 0 28px;
    color: var(--wp--preset--color--contrast);
  }

  .kuvaria-hero-v2__lede {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: 15px;
    line-height: 1.65;
    max-width: 44ch;
    margin: 0 0 32px;
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 78%, transparent);
  }

  /* CTA row — core/buttons. The buttons inherit the theme's .wp-block-button__link
     treatment (filled green + is-style-outline ghost), so no per-button CSS here. */
  .kuvaria-hero-v2__ctas { margin: 0; }

  .kuvaria-hero-v2__image.wp-block-column {
    position: relative;
    overflow: hidden;
    min-block-size: 300px;
  }

  /* Internal content pages — typographic rhythm + button treatment for content flow */

  /* Legacy default for internal-page h1s. Excludes the palvelut-v2 hero title
     (which owns its own orange styling) and is non-italic per client rule. */
  .wp-site-blocks h1.wp-block-heading:not(.palvelut-v2-hero__heading) {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(44px, 6vw, 72px);
    line-height: 1;
    margin-block-end: clamp(16px, 2vw, 28px);
    color: var(--wp--preset--color--contrast);
  }

  .wp-site-blocks h2.wp-block-heading {
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 400;
    font-size: clamp(30px, 3.5vw, 42px);
    line-height: 1.05;
    margin-block: clamp(48px, 6vw, 72px) 20px;
    color: var(--wp--preset--color--contrast);
  }

  .wp-site-blocks h3.wp-block-heading {
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 400;
    font-size: clamp(22px, 2vw, 28px);
    line-height: 1.1;
    margin-block: 28px 10px;
    color: var(--wp--preset--color--contrast);
  }

  /* Body font-family + size come from theme.json (styles.typography → body /
     medium = 16px). theme.json can't target a <p> specifically (core exposes
     `elements` only for links/headings/buttons), so the paragraph-specific
     Montserrat-Light weight + looser leading stay here — but NOT a hardcoded
     px size, which belongs to the preset system. */
  .wp-site-blocks p,
  .wp-site-blocks li {
    font-weight: 300;
    line-height: 1.7;
  }

  /* Content-flow links — green underlined, not applied to brand components.
     Both selectors carry the same exclusion chain: without it, `main a` (higher
     specificity than a component's own text-decoration:none) underlines + greens
     brand-component anchors that live inside <main> (e.g. the landing columns). */
  .wp-site-blocks main a:not(.wp-block-button__link):not(.kuvaria-landing-waves__col),
  .wp-site-blocks .wp-block-group a:not(.wp-block-button__link):not(.kuvaria-landing-waves__col) {
    color: var(--wp--preset--color--primary);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;

    &:hover,
    &:focus-visible { text-decoration-thickness: 2px; }
  }

  /* Core button block — green filled (default) / outlined */
  .wp-site-blocks .wp-block-button__link {
    font-family: var(--wp--preset--font-family--body);
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 14px 26px;
    border-radius: 0;

    &:not(.is-style-outline) {
      background: var(--wp--preset--color--primary);
      color: var(--wp--preset--color--base);

      &:hover,
      &:focus-visible { background: color-mix(in oklch, var(--wp--preset--color--primary) 85%, black); }
    }

    &.is-style-outline {
      background: transparent;
      color: var(--wp--preset--color--contrast);
      border: 1px solid var(--wp--preset--color--contrast);

      &:hover,
      &:focus-visible { background: var(--wp--preset--color--contrast); color: var(--wp--preset--color--base); }
    }
  }

  /* ── Teasers on /kivijalkaliike — three scalloped brand cards ────────────
     Editable: a core/columns row of kuvaria/scallop-card blocks (green/orange/
     pink). The card padding, scallop mask, colours, heading styling and link
     colour all come from blocks/scallop-card/style.css — only the section
     layout + the number/link polish live here. The heading is non-italic
     (client rule); the old card opacity-on-text is gone (cardinal CSS rule). */
  .kuvaria-teasers-section {
    /* Cap at wide-size so the section matches the hero's width. align:wide no
       longer caps it (the group is layout:default, not constrained), so without
       this it spans the full viewport on screens wider than 1440. */
    max-inline-size: var(--wp--style--global--wide-size, 1440px);
    margin-inline: auto;
    padding-block: clamp(64px, 10vw, 96px);
    padding-inline: clamp(28px, 5vw, 72px);
  }

  .kuvaria-teasers-section__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 40px;
    margin-block-end: clamp(36px, 5vw, 56px);
    flex-wrap: wrap;
  }

  .kuvaria-teasers-section__heading {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(36px, 5vw, 56px);
    line-height: 1;
    color: var(--wp--preset--color--contrast);
    margin: 0;
    max-width: 520px;
  }

  .kuvaria-teasers-section__intro {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: 14px;
    line-height: 1.65;
    max-width: 320px;
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 70%, transparent);
    margin: 0;
  }

  /* The 3 cards sit in core Columns; bump the gap a touch over the core default. */
  .kuvaria-teasers-grid { gap: clamp(1.25rem, 2.5vw, 1.75rem); }

  /* Number eyebrow + "read more" link inside each scallop card — inherit the
     card text colour (set by the block's own CSS), small + tracked. */
  .kuvaria-teaser-num {
    font-family: var(--wp--preset--font-family--heading);
    font-size: 15px;
    margin: 0;
    color: inherit;
  }

  .kuvaria-teaser-link {
    font-family: var(--wp--preset--font-family--body);
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-weight: 400;
    margin: 0;
  }
}

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

@layer utilities {
  /* Visually hidden but accessible to screen readers */
  .screen-reader-text {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* Text color utilities mapped to token scale */
  .has-muted-text {
    color: var(--wp--preset--color--muted, #64748b);
  }

  .has-success-text {
    color: var(--color-success, #16a34a);
  }

  .has-warning-text {
    color: var(--color-warning, #ca8a04);
  }

  .has-error-text {
    color: var(--color-error, #dc2626);
  }

  /* Raised surface with shadow */
  .has-raised-surface {
    background: var(--color-surface, #fff);
    box-shadow: var(--wp--preset--shadow--md);
    border-radius: var(--wp--preset--border--radius--medium, 0.5rem);
  }
}

/* ==========================================================================
   Overrides — Client-specific design enhancements (highest priority layer)
   ========================================================================== */

@layer overrides {
  /* ── Content width — 90% on narrow viewports ──────────────────────── */
  @media (max-width: 1280px) {
    .wp-site-blocks .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
      max-inline-size: min(1200px, 90%);
    }
  }

  /* ── Global ─────────────────────────────────────────────────────────── */
  ::selection {
    background: var(--wp--preset--color--primary);
    color: var(--wp--preset--color--base);
  }

  /* ── Footer ─────────────────────────────────────────────────────────── */
  /* Scalloped top edge: the dark footer field is cut into bumps so the cream
     page above shows through the troughs — a true mask cut (no painted shape),
     same family as .palvelut-hero-section / .palvelut-cta. Layer 1 keeps the
     body solid; layer 2 keeps a wavy top strip; default composite unions them.
     --kuvaria-footer-wave is the strip height — tuned live on staging. */
  .kuvaria-footer {
    position: relative;
    --kuvaria-footer-wave: 20px;
    -webkit-mask-image:
      linear-gradient(#000 0 0),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 24' preserveAspectRatio='none'%3E%3Cpath d='M 0,24 L 0,11 C 12,7 22,3 35,3 S 65,19 75,19 C 95,18 110,8 125,7 S 155,15 170,15 C 185,14 195,5 210,4 S 240,17 250,17 C 265,16 275,10 285,9 C 295,9 295,10 300,10 L 300,24 Z' fill='%23fff'/%3E%3C/svg%3E");
            mask-image:
      linear-gradient(#000 0 0),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 24' preserveAspectRatio='none'%3E%3Cpath d='M 0,24 L 0,11 C 12,7 22,3 35,3 S 65,19 75,19 C 95,18 110,8 125,7 S 155,15 170,15 C 185,14 195,5 210,4 S 240,17 250,17 C 265,16 275,10 285,9 C 295,9 295,10 300,10 L 300,24 Z' fill='%23fff'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat, no-repeat;
            mask-repeat: no-repeat, no-repeat;
    -webkit-mask-position: bottom, top;
            mask-position: bottom, top;
    -webkit-mask-size:
      100% calc(100% - (var(--kuvaria-footer-wave) - 1px)),
      100% var(--kuvaria-footer-wave);
            mask-size:
      100% calc(100% - (var(--kuvaria-footer-wave) - 1px)),
      100% var(--kuvaria-footer-wave);
  }

  /* Asymmetric two-zone composition: the invitation leads (focal, top-left),
     the brand cluster signs off (quieter, right). Sits clear of the scallop. */
  .kuvaria-footer-inner {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    gap: clamp(2rem, 6vw, 6rem);
    align-items: start;
    padding-block-start: clamp(0.5rem, 2vw, 1.5rem);
  }

  @media (max-width: 781px) {
    .kuvaria-footer-inner {
      grid-template-columns: 1fr;
      gap: clamp(2rem, 9vw, 3rem);
    }
  }

  /* Muted footer text (tagline, Y-tunnus, copyright): a dimmed cream, NOT the
     brown `muted` token (too low-contrast on ink) and NOT opacity (cardinal
     rule) — a real colour via color-mix so contrast computes correctly. */
  .kuvaria-footer .has-muted-color {
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 70%, var(--wp--preset--color--secondary));
  }

  /* ── Zone A: the invitation (focal) ─────────────────────────────────── */
  .kuvaria-footer-invite__title {
    margin: 0 0 clamp(1rem, 2.5vw, 1.6rem);
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal; /* client rule: never italic headings */
    font-weight: 400;
    line-height: 1.02;
    letter-spacing: -0.01em;
    font-size: clamp(2.4rem, 5vw, 3.6rem);
    color: var(--wp--preset--color--accent);
    text-wrap: balance;
  }

  /* Stacked data list: address → hours → phone → email. One uniform treatment,
     orange icons. Readability over emphasis (client direction). */
  .kuvaria-footer-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.95rem;
  }

  .kuvaria-footer-item {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    margin: 0;
  }

  /* Orange icons (accent), full strength — no opacity dimming */
  .kuvaria-footer-item svg {
    flex-shrink: 0;
    inline-size: 1.25rem;
    block-size: 1.25rem;
    margin-block-start: 0.18em;
    color: var(--wp--preset--color--accent);
  }

  /* Every row shares one font/size/weight (client: keep their fonts same).
     Also zeroes the wpautop <p> margin in the hours row + beats components p{300}. */
  .kuvaria-footer-item__text,
  .kuvaria-footer-item__text p {
    margin: 0;
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--medium);
    font-weight: 400;
    line-height: 1.5;
  }

  /* Footer links beat the @layer components rule that greens `.wp-block-group a` */
  .kuvaria-footer-item a {
    color: inherit;
    text-decoration: none;

    &:hover {
      text-decoration: underline;
      text-underline-offset: 3px;
      text-decoration-color: var(--wp--preset--color--accent);
    }
  }

  /* ── Zone B: the brand sign-off (quieter) ───────────────────────────── */
  .kuvaria-footer-brand {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.9rem;
  }

  /* Desktop: brand cluster aligns right, balancing the heading's left mass */
  @media (min-width: 782px) {
    .kuvaria-footer-brand {
      align-items: flex-end;
      text-align: right;
    }
  }

  .kuvaria-footer-logo {
    img {
      block-size: auto;
      inline-size: auto;
      max-block-size: 8.5rem; /* dialed back so the heading leads, not the logo */
    }

    .site-title {
      font-size: var(--wp--preset--font-size--2x-large);
      font-family: var(--wp--preset--font-family--heading);
      letter-spacing: 0.02em;
      text-decoration: none;
      color: inherit;
    }
  }

  .kuvaria-footer-tagline {
    margin: 0;
    font-size: var(--wp--preset--font-size--small);
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 70%, var(--wp--preset--color--secondary));
  }

  /* Social icon circles — soft pink with ink glyph (brand combo) */
  .kuvaria-social-icons {
    display: flex;
    gap: 0.65rem;
    margin-block-start: 1.1rem;

    a {
      display: flex;
      align-items: center;
      justify-content: center;
      inline-size: 2.4rem;
      block-size: 2.4rem;
      background: var(--wp--preset--color--contrast);
      border-radius: 50%;
      color: var(--wp--preset--color--base);
      text-decoration: none;
      transition:
        background var(--wp--custom--transition--fast, 150ms ease),
        transform var(--wp--custom--transition--fast, 150ms ease);

      /* Hover brightens (lighter ink) + lifts — never darkens. */
      &:hover {
        background: color-mix(in oklch, var(--wp--preset--color--contrast) 80%, white);
        transform: translateY(-2px);
      }
    }
  }

  /* Baseline strip — hairline rule + Y-tunnus / copyright row */
  .kuvaria-footer-rule {
    margin-block: clamp(3.5rem, 9vw, 6.25rem) var(--wp--preset--spacing--40);
    /* Border width + colour live in the unlayered escape hatch at the bottom of
       this file: core's UNLAYERED .wp-block-separator (2px solid currentColor)
       beats anything in @layer, so the hairline must be re-asserted unlayered. */
  }

  .kuvaria-footer-baseline {
    row-gap: 0.5rem;
    /* Three-part baseline: left / centre / right. grid (not the block's flex
       space-between) so the middle item is truly centred regardless of the
       left/right widths. !important beats WordPress's unlayered flex display. */
    display: grid !important;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 1rem;
  }
  .kuvaria-footer-baseline > :first-child  { justify-self: start;  text-align: start; }
  .kuvaria-footer-baseline > :nth-child(2) { justify-self: center; text-align: center; }
  .kuvaria-footer-baseline > :last-child   { justify-self: end;    text-align: end; }

  @media (max-width: 600px) {
    .kuvaria-footer-baseline {
      grid-template-columns: 1fr;
    }
    .kuvaria-footer-baseline > * {
      justify-self: center !important;
      text-align: center !important;
    }
  }

  /* ── Palvelut hero — orange section, bottom edge cut into a wave ───────── */
  /* True mask cut, not a painted shape: the section's own background is       */
  /* sliced at the bottom so whatever sits behind it (the page background)     */
  /* shows through the troughs. No hardcoded color that can fall out of sync.  */
  .palvelut-hero-section {
    position: relative;
    overflow: hidden;
    padding-block-start: calc(var(--wp--preset--spacing--90) * 2) !important;

    /* Layer 1: solid keep for everything above the bottom strip.
       Layer 2: wavy keep-region (white = kept) for the bottom 24px strip.
       Default mask-composite (add) unions them → section minus bottom troughs. */
    -webkit-mask-image:
      linear-gradient(#000 0 0),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 24' preserveAspectRatio='none'%3E%3Cpath d='M 0,0 L 0,13 C 12,17 22,21 35,21 S 65,5 75,5 C 95,6 110,16 125,17 S 155,9 170,9 C 185,10 195,19 210,20 S 240,7 250,7 C 265,8 275,14 285,15 C 295,15 295,14 300,14 L 300,0 Z' fill='%23fff'/%3E%3C/svg%3E");
            mask-image:
      linear-gradient(#000 0 0),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 24' preserveAspectRatio='none'%3E%3Cpath d='M 0,0 L 0,13 C 12,17 22,21 35,21 S 65,5 75,5 C 95,6 110,16 125,17 S 155,9 170,9 C 185,10 195,19 210,20 S 240,7 250,7 C 265,8 275,14 285,15 C 295,15 295,14 300,14 L 300,0 Z' fill='%23fff'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat, no-repeat;
            mask-repeat: no-repeat, no-repeat;
    -webkit-mask-position: top, bottom;
            mask-position: top, bottom;
    -webkit-mask-size: 100% calc(100% - 23px), 100% 24px;
            mask-size: 100% calc(100% - 23px), 100% 24px;
  }

  /* ── Palvelut CTA — green box, all four edges cut into waves ───────────── */
  /* Same true-cut approach: the green box's own background is masked on each  */
  /* edge so the section behind shows through the troughs. Robust to any       */
  /* background-color change — there is no painted fill colour to keep synced. */
  .palvelut-cta,
  .is-style-scallop-cta {
    position: relative;
    overflow: hidden;

    /* These !important flags are load-bearing, not sloppiness: component rules
       live in @layer components, which LOSES the cascade to WordPress's
       unlayered block/layout/colour styles. Without them an alignfull/layout
       width or the default link colour could win. */
    width: min(var(--wp--style--global--content-size, 1200px), 100%) !important;
    max-inline-size: var(--wp--style--global--content-size, 1200px) !important;
    margin-inline: auto !important;
    margin-block-start: var(--wp--preset--spacing--80) !important;
    margin-block-end: clamp(3rem, 6vw, 5rem) !important;

    /* Padding = breathing room between content and the scalloped mask edges.
       The block no longer sets inline padding, so CSS owns it outright — no
       !important needed (nothing competes for a group's padding). */
    padding-block: var(--wp--preset--spacing--80);
    padding-inline: clamp(2.5rem, 5vw, 4.5rem);

    /* Light text on the green box (same @layer reason as the width flags). */
    color: var(--wp--preset--color--base) !important;

    /* One mask path traces the whole box outline — waves on all four edges,
       meeting cleanly at the inset corners as a single coherent shape. No
       compositing, so no corner overlap. viewBox is ~3:1 to match the box so
       wave depth stays roughly even on every edge; it scales with the box. */
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 200' preserveAspectRatio='none'%3E%3Cpath d='M 12,12 Q 60,-12 108,12 Q 156,-12 204,12 Q 252,-12 300,12 Q 348,-12 396,12 Q 444,-12 492,12 Q 540,-12 588,12 Q 612,56 588,100 Q 612,144 588,188 Q 540,212 492,188 Q 444,212 396,188 Q 348,212 300,188 Q 252,212 204,188 Q 156,212 108,188 Q 60,212 12,188 Q -12,144 12,100 Q -12,56 12,12 Z' fill='%23fff'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 200' preserveAspectRatio='none'%3E%3Cpath d='M 12,12 Q 60,-12 108,12 Q 156,-12 204,12 Q 252,-12 300,12 Q 348,-12 396,12 Q 444,-12 492,12 Q 540,-12 588,12 Q 612,56 588,100 Q 612,144 588,188 Q 540,212 492,188 Q 444,212 396,188 Q 348,212 300,188 Q 252,212 204,188 Q 156,212 108,188 Q 60,212 12,188 Q -12,144 12,100 Q -12,56 12,12 Z' fill='%23fff'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: 100% 100%;
            mask-size: 100% 100%;

    /* Tablet: the inner columns have stacked (WP core default <=781px) so the
       box is roughly square. The ~3:1 desktop path would stretch flat on the
       sides here — swap to a ~1:1 path so neither axis distorts. */
    @media (min-width: 600px) and (max-width: 781px) {
      -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 280 240' preserveAspectRatio='none'%3E%3Cpath d='M 12,12 Q 44,-12 76,12 Q 108,-12 140,12 Q 172,-12 204,12 Q 236,-12 268,12 Q 292,39 268,66 Q 292,93 268,120 Q 292,147 268,174 Q 292,201 268,228 Q 236,252 204,228 Q 172,252 140,228 Q 108,252 76,228 Q 44,252 12,228 Q -12,201 12,174 Q -12,147 12,120 Q -12,93 12,66 Q -12,39 12,12 Z' fill='%23fff'/%3E%3C/svg%3E");
              mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 280 240' preserveAspectRatio='none'%3E%3Cpath d='M 12,12 Q 44,-12 76,12 Q 108,-12 140,12 Q 172,-12 204,12 Q 236,-12 268,12 Q 292,39 268,66 Q 292,93 268,120 Q 292,147 268,174 Q 292,201 268,228 Q 236,252 204,228 Q 172,252 140,228 Q 108,252 76,228 Q 44,252 12,228 Q -12,201 12,174 Q -12,147 12,120 Q -12,93 12,66 Q -12,39 12,12 Z' fill='%23fff'/%3E%3C/svg%3E");
    }

    /* Stacked mobile layout makes the box tall + narrow; the ~3:1 desktop mask
       would stretch unevenly. Swap to a portrait (~1:2) path so the wave depth
       and spacing stay even on the now-tall side edges. */
    @media (max-width: 599px) {
      -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 360' preserveAspectRatio='none'%3E%3Cpath d='M 12,12 Q 38,-12 64,12 Q 90,-12 116,12 Q 142,-12 168,12 Q 192,40 168,68 Q 192,96 168,124 Q 192,152 168,180 Q 192,208 168,236 Q 192,264 168,292 Q 192,320 168,348 Q 142,372 116,348 Q 90,372 64,348 Q 38,372 12,348 Q -12,320 12,292 Q -12,264 12,236 Q -12,208 12,180 Q -12,152 12,124 Q -12,96 12,68 Q -12,40 12,12 Z' fill='%23fff'/%3E%3C/svg%3E");
              mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 360' preserveAspectRatio='none'%3E%3Cpath d='M 12,12 Q 38,-12 64,12 Q 90,-12 116,12 Q 142,-12 168,12 Q 192,40 168,68 Q 192,96 168,124 Q 192,152 168,180 Q 192,208 168,236 Q 192,264 168,292 Q 192,320 168,348 Q 142,372 116,348 Q 90,372 64,348 Q 38,372 12,348 Q -12,320 12,292 Q -12,264 12,236 Q -12,208 12,180 Q -12,152 12,124 Q -12,96 12,68 Q -12,40 12,12 Z' fill='%23fff'/%3E%3C/svg%3E");
    }

    h1, h2, h3, h4, h5, h6, p, li, a:not(.wp-block-button__link) {
      color: var(--wp--preset--color--base) !important;
    }
  }

  /* Ajankohtaista — scallop card at content width, with a little more breathing
     room above than the default scallop margin (spacing-80 → spacing-90). */
  .palvelut-ajankohtaista {
    margin-block-start: var(--wp--preset--spacing--90) !important;
  }
  .palvelut-ajankohtaista .wp-block-image img {
    width: 100%;
    height: auto;
    display: block;
  }

  /* ── Palvelut intro — image above text on mobile ──────────────────────── */
  @media (max-width: 599px) {
    .palvelut-intro-columns .wp-block-column:last-child {
      order: -1;
    }
  }

  /* ── Palvelut gallery — full-bleed 3-column portrait grid ─────────────── */
  /* The alignfull constrained group has .has-global-padding which adds      */
  /* padding-inline equal to the root padding (--wp--style--root--padding-*) */
  /* We compensate exactly the same way WordPress does for alignfull blocks.  */
  .palvelut-gallery {
    max-inline-size: none !important;
    width: calc(100% + var(--wp--style--root--padding-left, 0px) + var(--wp--style--root--padding-right, 0px));
    margin-inline-start: calc(-1 * var(--wp--style--root--padding-left, 0px)) !important;
    margin-inline-end: calc(-1 * var(--wp--style--root--padding-right, 0px)) !important;
    margin-block: var(--wp--preset--spacing--80) !important;
    display: flex;
    flex-wrap: wrap;

    figure.wp-block-image {
      flex: 0 0 50%;
      max-width: 50%;
      margin: 0;

      @media (min-width: 600px) {
        flex: 0 0 calc(100% / 3);
        max-width: calc(100% / 3);
      }

      img {
        display: block;
        width: 100%;
        aspect-ratio: 3 / 4;
        object-fit: cover;
      }
    }
  }

}


/* ==========================================================================
   Keyframes — Outside @layer so they're globally accessible
   ========================================================================== */

@keyframes clipPathCircleOpen {
  0% {
    clip-path: circle(0% at top right);
  }
  100% {
    clip-path: circle(250% at top right);
  }
}


@keyframes clipPathCircleClose {
  0% {
    clip-path: circle(250% at top right);
  }
  100% {
    clip-path: circle(0% at top right);
  }
}

/* ============================================================
   PALVELUT v2 — funky checkerboard redesign (Impeccable shape).
   New classes only; the original palvelut page is untouched.
   Pays off the landing portal: full-palette, image-forward, NO
   italic headings, colour-on-colour display per the client's
   cream<->orange and green<->pink combos; ink reserved for body.
   ============================================================ */
@layer components {

  /* — Hero: calm cream intro, constrained, no scallop (the page is cream) — */
  .palvelut-v2-hero {
    max-inline-size: var(--wp--style--global--wide-size, 1440px);
    margin-inline: auto;
    padding-block: clamp(4rem, 8vw, 7rem) clamp(1.5rem, 4vw, 3rem);
    padding-inline: clamp(1.25rem, 4vw, 3rem);
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    align-items: end;
    gap: clamp(1.5rem, 4vw, 4rem);
  }

  @media (max-width: 640px) {
    .palvelut-v2-hero { grid-template-columns: 1fr; align-items: start; }
  }

  /* Title lockup — a real, editable core/image logo beside the heading. The
     wrapper is the flex row; the heading carries the type. (Replaces the old
     CSS-only ::before logo — now a client-editable image block on every hero.) */
  .palvelut-v2-hero__title {
    display: flex;
    align-items: center;
    gap: clamp(0.75rem, 1.8vw, 1.4rem);
    margin: 0;
  }
  .palvelut-v2-hero__logo {
    flex-shrink: 0;
    margin: 0;
  }
  .palvelut-v2-hero__logo img {
    display: block;
    block-size: clamp(3.25rem, 6.5vw, 5rem);
    inline-size: auto;
  }
  .palvelut-v2-hero__heading {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    /* max trimmed 6→5rem so long single-word titles (Yhteystiedot) fit the
       hero's title column without an ugly mid-word break. */
    font-size: clamp(2.5rem, 6vw, 5rem);
    line-height: 0.92;
    letter-spacing: -0.02em;
    margin: 0;
    color: var(--wp--preset--color--accent);
    text-wrap: balance;
  }

  .palvelut-v2-hero__lead {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.55;
    margin: 0;
    max-inline-size: 44ch;
    color: var(--wp--preset--color--contrast);
  }
  .palvelut-v2-hero__lead a {
    color: var(--wp--preset--color--primary);
    text-underline-offset: 3px;
    text-decoration-thickness: 2px;
  }

  /* — Mosaic: constrained outer + a grid that tracks its OWN width — */
  .palvelut-v2-mosaic {
    container-type: inline-size;
    max-inline-size: var(--wp--style--global--wide-size, 1440px);
    margin-inline: auto;
    padding-block: clamp(1rem, 3vw, 2.5rem) clamp(2.5rem, 6vw, 5rem);
    padding-inline: clamp(1.25rem, 4vw, 3rem);
  }
  .palvelut-v2-mosaic__grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(0.5rem, 1.2vw, 1rem);
  }
  /* Container queries (track the mosaic's own width, NOT the viewport): the
     block editor caps page content at ~960px while the front-end template is
     full-width (1440). A viewport media query kept 4 narrow columns in the
     editor, ballooning the cards (and the photos that cover those tall rows).
     @container tracks the real container, fixing the editor + real mobile. */
  @container (max-width: 1100px) {
    .palvelut-v2-mosaic__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @container (max-width: 560px) {
    .palvelut-v2-mosaic__grid { grid-template-columns: minmax(0, 1fr); }
  }

  /* Content vertically centred so it clears the wavy top/bottom cuts.
     margin:0 also resets the <figure> UA margin on photo cells. */
  .palvelut-v2-cell {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: clamp(0.5rem, 1.5vw, 1rem);
    padding: clamp(1.75rem, 3vw, 2.5rem);
    min-block-size: clamp(170px, 18vw, 230px);
    margin: 0;
  }

  .palvelut-v2-cell__name {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(1.4rem, 2.1vw, 2.1rem);
    line-height: 1.02;
    letter-spacing: -0.01em;
    margin: 0;
    text-wrap: balance;
    /* Heading: controlled wrap, NO auto-hyphens (avoids mid-compound display
       breaks like "jää-telö"). See feedback_finnish_hyphenation. */
    hyphens: manual;
    overflow-wrap: break-word;
  }
  .palvelut-v2-cell__desc {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: 1rem;
    line-height: 1.5;
    margin: 0;
    hyphens: auto;
    overflow-wrap: break-word;
  }

  /* Colour cards — bold scalloped outline on every edge (the wave moved here
     from the hero). One single-shape mask traces the whole card; the troughs
     reveal the cream page behind. Cards are orange/green/pink only — a cream
     card would vanish on the cream page. NAMES use the client's combos; body
     DESC uses the contrast-safe choice per cell. */
  .palvelut-v2-cell--orange,
  .palvelut-v2-cell--green,
  .palvelut-v2-cell--pink {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 240' preserveAspectRatio='none'%3E%3Cpath d='M 0,0 C 25,0 50,20 75,20 C 100,20 125,0 150,0 C 175,0 200,20 225,20 C 250,20 275,0 300,0 C 300,20 280,40 280,60 C 280,80 300,100 300,120 C 300,140 280,160 280,180 C 280,200 300,220 300,240 C 275,240 250,220 225,220 C 200,220 175,240 150,240 C 125,240 100,220 75,220 C 50,220 25,240 0,240 C 0,220 20,200 20,180 C 20,160 0,140 0,120 C 0,100 20,80 20,60 C 20,40 0,20 0,0 Z' fill='%23fff'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 240' preserveAspectRatio='none'%3E%3Cpath d='M 0,0 C 25,0 50,20 75,20 C 100,20 125,0 150,0 C 175,0 200,20 225,20 C 250,20 275,0 300,0 C 300,20 280,40 280,60 C 280,80 300,100 300,120 C 300,140 280,160 280,180 C 280,200 300,220 300,240 C 275,240 250,220 225,220 C 200,220 175,240 150,240 C 125,240 100,220 75,220 C 50,220 25,240 0,240 C 0,220 20,200 20,180 C 20,160 0,140 0,120 C 0,100 20,80 20,60 C 20,40 0,20 0,0 Z' fill='%23fff'/%3E%3C/svg%3E");
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: 100% 100%;
            mask-size: 100% 100%;
  }

  .palvelut-v2-cell--orange { background: var(--wp--preset--color--accent); }
  .palvelut-v2-cell--orange .palvelut-v2-cell__name { color: var(--wp--preset--color--base); }
  .palvelut-v2-cell--orange .palvelut-v2-cell__desc { color: var(--wp--preset--color--contrast); }

  .palvelut-v2-cell--green { background: var(--wp--preset--color--primary); }
  .palvelut-v2-cell--green .palvelut-v2-cell__name { color: var(--wp--preset--color--secondary); }
  .palvelut-v2-cell--green .palvelut-v2-cell__desc { color: var(--wp--preset--color--base); }

  .palvelut-v2-cell--pink { background: var(--wp--preset--color--secondary); }
  .palvelut-v2-cell--pink .palvelut-v2-cell__name { color: var(--wp--preset--color--primary); }
  .palvelut-v2-cell--pink .palvelut-v2-cell__desc { color: var(--wp--preset--color--contrast); }

  /* Photo cells (kuvaria/mosaic-photo): the cover-fill rules live in the
     UNLAYERED escape hatch at the bottom of this file — the block editor's
     unlayered img reset (height:auto) beats a layered rule (feedback_wp_layer_trap),
     so the photos blew up to full size inside the editor. Unlayered wins in both. */

  /* ── Hinnasto — pricing page ───────────────────────────────────────────
     Same family as palvelut-v2: cream page, each <h2> section becomes a
     two-column row (scalloped colour card holding the heading on the left,
     pricing data on the right). Reuses the cell scallop mask + the .palvelut-cta
     green block (in the page content). Card text colours are AA-safe — ink on
     the orange card (cream-on-orange fails AA, the Issue #3 trap), cream on
     green, green on pink (passes as large display text). */

  /* Hero — reuses .palvelut-v2-hero (same two-column grid, wide-size, orange
     title) so the page opens identically to palvelut-v2. No hinnasto-specific
     hero rules needed. */

  /* Section row — core Columns at wide-size (colour card column : data column).
     The card is a kuvaria/scallop-card block (its own mask + colours); the data
     column is .hinnasto-data. Stacks on mobile via core's column stacking. */
  .hinnasto-section {
    max-inline-size: var(--wp--style--global--wide-size, 1440px);
    margin-inline: auto;
    padding-inline: clamp(1.25rem, 4vw, 3rem);
    padding-block: clamp(1.25rem, 3vw, 2.25rem);
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: start;
  }

  /* Flagship price — big display number inside the orange scallop card. Ink
     (contrast) so it reads as a price tag; ink-on-orange is AA-safe. Only the
     passikuva card carries a price. Lives inside the card as an editable
     paragraph with the .hinnasto-price class. */
  .hinnasto-price {
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 400;
    font-size: clamp(3rem, 6vw, 4.5rem);
    line-height: 0.92;
    letter-spacing: -0.02em;
    margin: 0;
    color: var(--wp--preset--color--contrast);
    font-variant-numeric: tabular-nums;
  }

  /* Teaser "from" price inside the green/pink cards — smaller than the flagship
     number and inherits the card's text colour (cream on green, ink on pink),
     so it stays AA-safe per card. */
  .hinnasto-price-from {
    font-family: var(--wp--preset--font-family--heading);
    font-weight: 400;
    font-size: clamp(1.6rem, 2.6vw, 2.2rem);
    line-height: 1;
    letter-spacing: -0.01em;
    margin: 0;
    font-variant-numeric: tabular-nums;
  }

  /* Data column — prose + price table, controlled vertical rhythm. */
  .hinnasto-data {
    display: flex;
    flex-direction: column;
    gap: clamp(0.75rem, 2vw, 1.1rem);
    /* nudge content down so it aligns with the card's vertically-centred title */
    padding-block-start: clamp(0.25rem, 1.5vw, 1.25rem);
  }
  .hinnasto-data p {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.55;
    margin: 0;
    max-inline-size: 62ch;
    color: var(--wp--preset--color--contrast);
    /* Finnish body copy: auto syllabification (ceiling, where the browser has
       the fi dict) stacked with hand-rolled &shy; seams in the content (floor,
       for no-dict Chrome on Windows/Android). See feedback_finnish_hyphenation. */
    text-wrap: pretty;
    hyphens: auto;
  }
  .hinnasto-subhead {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(1.15rem, 1.6vw, 1.4rem);
    margin: 0.5rem 0 0;
    color: var(--wp--preset--color--primary);
  }

  /* Brand price table (is-style-hinnasto on core/table) lives in the UNLAYERED
     escape hatch at the bottom of this file — it must beat WordPress core's
     unlayered .wp-block-table cell CSS, which @layer rules can't win against
     (see feedback_wp_layer_trap). */

  /* ── Yhteystiedot — contact page ───────────────────────────────────────
     Layout is native + client-editable: core Columns (align wide = 1440) hold
     the green kuvaria/scallop-card block (with the kuvaria/contact-* blocks
     inside) + the laskutus below it, and the form column. The card itself is
     the Scallop Card block (blocks/scallop-card/); only the laskutus + form
     styling lives here. */

  /* Width follows the set direction (wide-size = 1440), matching hinnasto/
     palvelut. The full-width page-yhteystiedot.html template lets the columns
     own their max-width (the default constrained template caps them at 960).
     The hero self-widths via .palvelut-v2-hero. */
  .yhteystiedot-columns {
    max-inline-size: var(--wp--style--global--wide-size, 1440px);
    margin-inline: auto;
    padding-inline: clamp(1.25rem, 4vw, 3rem);
    gap: clamp(2.5rem, 5vw, 5rem);
  }

  /* Laskutus — quiet billing detail under the card, on the cream page. */
  .yhteystiedot-laskutus {
    padding-inline: clamp(0.5rem, 2vw, 1.5rem);
  }
  .yhteystiedot-laskutus__title {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: 1.05rem;
    margin: 0 0 0.4rem;
    color: var(--wp--preset--color--contrast);
  }
  .yhteystiedot-laskutus p {
    margin: 0;
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: var(--wp--preset--font-size--small);
    line-height: 1.6;
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 62%, transparent);
  }

  /* Form column */
  .yhteystiedot-form__title {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(1.8rem, 2.8vw, 2.5rem);
    line-height: 1.04;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--wp--preset--color--contrast);
    text-wrap: balance;
  }
  .yhteystiedot-form__intro {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 300;
    font-size: var(--wp--preset--font-size--medium);
    line-height: 1.55;
    margin: 0.75rem 0 1.75rem;
    max-inline-size: 50ch;
    color: var(--wp--preset--color--contrast);
  }

  /* CF7 fields — scoped, on-brand: soft cream inputs, brand focus + submit. */
  .yhteystiedot-form .wpcf7-form label {
    display: block;
    font-family: var(--wp--preset--font-family--body);
    font-weight: 400;
    font-size: var(--wp--preset--font-size--small);
    color: var(--wp--preset--color--contrast);
    margin-block-end: 1rem;
  }
  .yhteystiedot-form input[type="text"],
  .yhteystiedot-form input[type="email"],
  .yhteystiedot-form input[type="tel"],
  .yhteystiedot-form textarea {
    inline-size: 100%;
    margin-block-start: 0.35rem;
    padding: 0.7rem 0.9rem;
    font-family: var(--wp--preset--font-family--body);
    font-size: var(--wp--preset--font-size--medium);
    color: var(--wp--preset--color--contrast);
    background: color-mix(in oklch, var(--wp--preset--color--base) 55%, white);
    border: 1px solid color-mix(in oklch, var(--wp--preset--color--contrast) 22%, transparent);
    border-radius: 6px;
  }
  .yhteystiedot-form input:focus-visible,
  .yhteystiedot-form textarea:focus-visible {
    outline: 2px solid var(--wp--preset--color--primary);
    outline-offset: 1px;
    border-color: transparent;
  }
  .yhteystiedot-form textarea {
    min-block-size: 8rem;
    resize: vertical;
  }
  .yhteystiedot-form .wpcf7-acceptance {
    display: block;
    margin-block: 0.25rem 1.25rem;
    font-size: var(--wp--preset--font-size--small);
  }
  .yhteystiedot-form .wpcf7-acceptance .wpcf7-list-item {
    margin: 0;
  }
  .yhteystiedot-form .wpcf7-acceptance a {
    color: var(--wp--preset--color--primary);
    text-underline-offset: 2px;
  }
  .yhteystiedot-form .wpcf7-submit {
    font-family: var(--wp--preset--font-family--body);
    font-weight: 400;
    font-size: var(--wp--preset--font-size--medium);
    color: var(--wp--preset--color--base);
    background: var(--wp--preset--color--primary);
    border: none;
    border-radius: 6px;
    padding: 0.8rem 2rem;
    cursor: pointer;
    transition: background 0.15s ease;
  }
  .yhteystiedot-form .wpcf7-submit:hover {
    background: color-mix(in oklch, var(--wp--preset--color--primary) 85%, white);
  }
}


/* ==========================================================================
   Blog — /blogi/ index (home) + category/tag archives + single post
   Owns the editorial-card grid and the single-post reading view. Cards stay
   calm for legibility; brand energy is limited to the wave divider, the
   brand-green "Lue lisää" link, and a gentle card hover-lift.
   ========================================================================== */
@layer components {
  /* The blog index header reuses .palvelut-v2-hero (logo + heading + lead) —
     see home.html; no bespoke header CSS needed here.
     Card grid — graceful from a single post upward: capped tracks, centered. */
  .kuvaria-blog-grid {
    margin-block-start: clamp(2rem, 5vw, 3.75rem);
  }
  .kuvaria-blog-grid .wp-block-post-template.is-layout-grid {
    grid-template-columns: repeat(auto-fill, minmax(300px, 460px));
    justify-content: center;
    gap: clamp(1.5rem, 3vw, 2.5rem);
  }

  .kuvaria-blog-grid .wp-block-post {
    display: flex;
    flex-direction: column;
    background: var(--wp--preset--color--base);
    border: 1px solid color-mix(in oklch, var(--wp--preset--color--contrast) 12%, transparent);
    border-radius: 10px;
    overflow: hidden;
    transition: transform 250ms ease, box-shadow 250ms ease;
  }
  .kuvaria-blog-grid .wp-block-post:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 28px -12px color-mix(in oklch, var(--wp--preset--color--contrast) 35%, transparent);
  }
  .kuvaria-blog-grid .wp-block-post-title {
    font-family: var(--wp--preset--font-family--heading);
    font-style: normal;
    font-weight: 400;
    font-size: clamp(1.35rem, 1.8vw, 1.7rem);
    line-height: 1.12;
    margin-block: 0.9rem 0.4rem;
    padding-inline: clamp(1rem, 2vw, 1.4rem);
  }
  .kuvaria-blog-grid .wp-block-post-title a {
    color: var(--wp--preset--color--contrast);
    text-decoration: none;
  }
  .kuvaria-blog-grid .wp-block-post-title a:hover {
    color: var(--wp--preset--color--primary);
  }
  .kuvaria-blog-grid .wp-block-post-date {
    padding-inline: clamp(1rem, 2vw, 1.4rem);
    font-size: 0.8rem;
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 55%, var(--wp--preset--color--base));
  }
  .kuvaria-blog-grid .wp-block-post-excerpt {
    padding: 0.55rem clamp(1rem, 2vw, 1.4rem) clamp(1.1rem, 2.4vw, 1.6rem);
  }
  .kuvaria-blog-grid .wp-block-post-excerpt p {
    margin: 0;
    font-weight: 300;
    line-height: 1.55;
  }
  .kuvaria-blog-grid .wp-block-post-excerpt__more-link {
    display: inline-block;
    margin-block-start: 0.6rem;
    color: var(--wp--preset--color--primary);
    text-decoration: none;
  }
  .kuvaria-blog-grid .wp-block-post-excerpt__more-link:hover {
    text-decoration: underline;
  }

  /* Single post — calm, capped reading column. */
  .kuvaria-single-meta {
    margin-block: 0.5rem 1.6rem;
    font-size: 0.85rem;
    color: color-mix(in oklch, var(--wp--preset--color--contrast) 55%, var(--wp--preset--color--base));
  }
  .kuvaria-single-content {
    max-inline-size: 68ch;
    margin-inline: auto;
  }
  /* Restore list styling inside post content — the base reset strips ul/ol
     bullets + indent site-wide (fine for nav/layout lists, wrong for prose). */
  .kuvaria-single-content :is(ul, ol) {
    margin-block: 1.1em;
    padding-inline-start: 1.5em;
  }
  .kuvaria-single-content ul { list-style: disc; }
  .kuvaria-single-content ol { list-style: decimal; }
  .kuvaria-single-content li { margin-block: 0.35em; }
  .kuvaria-single-content li::marker { color: var(--wp--preset--color--primary); }
  .kuvaria-back-to-blog a {
    color: var(--wp--preset--color--primary);
    text-decoration: none;
  }
  .kuvaria-back-to-blog a:hover {
    text-decoration: underline;
  }
}

/* Unlayered escape hatch — core's .wp-block-post-featured-image CSS is enqueued
   UNLAYERED and beats @layer rules (see feedback_wp_layer_trap). Keep the card
   image flush + filling its 4/3 box here so it wins without !important. */
.kuvaria-blog-grid .wp-block-post-featured-image {
  margin: 0;
}
.kuvaria-blog-grid .wp-block-post-featured-image img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
/* Card excerpt: readable muted ink. Unlayered so it beats theme.json's
   zero-specificity :where(.wp-block-post-excerpt) global-styles rule; the
   theme.json default (now contrast) covers any excerpt outside a card. */
.kuvaria-blog-grid .wp-block-post-excerpt,
.kuvaria-blog-grid .wp-block-post-excerpt p {
  color: color-mix(in oklch, var(--wp--preset--color--contrast) 82%, var(--wp--preset--color--base));
}
/* Single-post title: the theme sizes h1.wp-block-heading (the .wp-block-heading
   rule up top) but NOT .wp-block-post-title, so the post title falls tiny. Match
   the heading scale. Unlayered + (0,2,2) to beat the has-*-font-size preset. */
.wp-site-blocks h1.wp-block-post-title {
  font-size: clamp(40px, 5.5vw, 64px);
  line-height: 1.05;
  margin-block-end: clamp(0.75rem, 1.6vw, 1.4rem);
}
/* Single-post featured image: full wide-width band, cover-cropped to a capped
   height so a portrait source doesn't tower; centred by align:wide. Margin
   below separates it from the body. Unlayered to beat core's featured-image img
   rules (see feedback_wp_layer_trap). */
.kuvaria-single-featured {
  /* Re-center the alignwide figure: core's .wp-block-post-featured-image{margin:0}
     kills the constrained-layout auto margins, so restore them here. */
  margin-inline: auto;
  margin-block-end: clamp(2rem, 5vw, 3.5rem);
}
.kuvaria-single-featured img {
  inline-size: 100%;
  block-size: clamp(320px, 42vh, 540px);
  object-fit: cover;
  display: block;
}

/* ── Unlayered escape hatch ─────────────────────────────────────────────── */
/* WordPress core's separator style is UNLAYERED — `.wp-block-separator { border:
   2px solid currentColor }` (top-only) — so it beats every @layer rule, forcing
   the footer rule to a solid 2px line regardless of what @layer overrides says.
   Re-assert the intended 1px faint hairline here: unlayered + higher specificity
   (.kuvaria-footer .kuvaria-footer-rule) so both width and colour actually win. */
.kuvaria-footer .kuvaria-footer-rule {
  border-top-width: 1px;
  border-top-color: color-mix(in oklch, var(--wp--preset--color--contrast) 22%, transparent);
}

/* Brand price table — the `is-style-hinnasto` block style on core/table.
   UNLAYERED because WordPress core's .wp-block-table cell CSS is unlayered and
   beats any @layer rule (feedback_wp_layer_trap). Soft ink dividers (no core
   striping), faint pink even-row tint, right-aligned tabular prices. */
.wp-block-table.is-style-hinnasto { margin: 0; }
.wp-block-table.is-style-hinnasto table {
  inline-size: 100%;
  border-collapse: collapse;
  margin: 0;
  font-family: var(--wp--preset--font-family--body);
  font-weight: 300;
  font-size: 1rem;
  color: var(--wp--preset--color--contrast);
}
.wp-block-table.is-style-hinnasto th,
.wp-block-table.is-style-hinnasto td {
  text-align: start;
  padding: 0.7rem 0.9rem;
  border: 0;
  border-block-end: 1px solid color-mix(in oklch, var(--wp--preset--color--contrast) 12%, transparent);
  vertical-align: baseline;
}
.wp-block-table.is-style-hinnasto thead th {
  font-family: var(--wp--preset--font-family--heading);
  font-weight: 400;
  border-block-end: 2px solid var(--wp--preset--color--accent);
}
.wp-block-table.is-style-hinnasto tbody tr:nth-child(even) td {
  background: color-mix(in oklch, var(--wp--preset--color--secondary) 20%, transparent);
}
.wp-block-table.is-style-hinnasto tbody tr:last-child td { border-block-end: none; }
.wp-block-table.is-style-hinnasto th:last-child,
.wp-block-table.is-style-hinnasto td:last-child {
  text-align: end;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Hero logo (core/image) sizing — UNLAYERED because core's .wp-block-image img
   { height:auto } is unlayered and beats a layered rule of equal specificity
   (feedback_wp_layer_trap). Theme sheet loads after core, so this wins by order. */
.palvelut-v2-hero__logo img {
  block-size: clamp(3.25rem, 6.5vw, 5rem);
  inline-size: auto;
}

/* Mosaic photo cells (kuvaria/mosaic-photo) — UNLAYERED so the cover-fill wins
   over both the block editor's unlayered img reset (height:auto, which blew the
   photos up full-size in the editor) and core's unlayered figure margin
   (feedback_wp_layer_trap). The image fills the cell via absolute positioning. */
.palvelut-v2-cell--photo {
  padding: 0;
  margin: 0;
  position: relative;
  overflow: hidden;
  min-block-size: clamp(170px, 18vw, 230px);
}
.palvelut-v2-cell--photo img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}

/* Kivijalkaliike hero image (core/image) — UNLAYERED so the cover-fill beats
   core's unlayered figure margin + img height:auto (feedback_wp_layer_trap).
   Absolute-filled like the mosaic photos: the image covers the right column at
   any height (desktop = stretched to the text column; mobile = the 300px floor)
   without adding flow height of its own. */
.kuvaria-hero-v2__image .wp-block-image {
  margin: 0;
  position: absolute;
  inset: 0;
}
.kuvaria-hero-v2__image .wp-block-image img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}

/* Buttons — UNLAYERED. The theme's square-button intent lived in @layer
   components, but core/global-styles emits an UNLAYERED button rule (pill
   radius:9999px + core padding) that beats every @layer (feedback_wp_layer_trap).
   Re-assert the design here so it actually wins: square corners + the chunkier
   brand padding. Colour/uppercase/font already win (core doesn't set them). */
.wp-site-blocks .wp-block-button__link {
  border-radius: 0;
  padding: 14px 26px;
}

/* "Linkki" button style (is-style-link) — an underlined text link, no box,
   border or fill. For secondary CTAs ("Ota yhteyttä") and outbound links; the
   label inherits the surrounding text colour so it works on any background. */
.wp-site-blocks .wp-block-button.is-style-link .wp-block-button__link {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.wp-site-blocks .wp-block-button.is-style-link .wp-block-button__link:hover,
.wp-site-blocks .wp-block-button.is-style-link .wp-block-button__link:focus-visible {
  text-decoration-thickness: 2px;
}

/* Hero CTA row spacing — UNLAYERED so the gap beats core's .wp-block-buttons
   flex gap. align-items:center lines the underlined secondary link up with the
   filled primary button (different heights). */
.wp-site-blocks .kuvaria-hero-v2__ctas {
  gap: 24px;
  align-items: center;
}
