/* ==========================================================================
   KETNAL CREATIONS — FOUNDATION
   Tokens, resets, typography, buttons, motion primitives, Divi neutralisers.
   Section-specific rules live in ketnal-sections.css.

   Two rules govern this file:
   1. Nothing a visitor can click ever moves. Buttons and links change colour,
      border and glow only. No translate, no scale, no rotate on hover.
   2. Nothing animates a property that triggers layout. Only opacity, filter
      and transform, and only on elements that are contained or positioned.
   ========================================================================== */

/* --------------------------------------------------------------- 1. Tokens */

:root {
  /* Surfaces — a near-black with a violet bias so the ember reads warm */
  --k-ink-950: #07050a;
  --k-ink-900: #0a0710;
  --k-ink-850: #0e0a16;
  --k-ink-800: #140e1e;
  --k-ink-700: #1e1526;
  --k-ink-600: #2a1e33;

  /* Brand — drawn from the sphere in the Ketnal mark */
  --k-ember: #ff2d55;
  --k-ember-soft: #ff6b84;
  --k-ember-deep: #9b1c34;
  --k-orchid: #c81e7a;
  --k-orchid-soft: #f25cae;
  --k-orchid-deep: #7a1259;

  /* Ink on dark. Lifted from the original prototype values: at #a99ba6 and 55%
     alpha, body copy sat around 7:1 on flat black but read as washed out over
     the hero imagery behind it. These clear 9:1 against the ink and stay
     legible over a lit background. */
  --k-chalk: #f7f4f6;
  --k-mute: #c3b8bf;
  --k-faint: rgba(247, 244, 246, 0.78);
  --k-bone: #f4ede3;

  /* Per-page accent. Sections read this, never a hard-coded hue, so a page
     can shift its glow without forking the design system. */
  --k-accent: var(--k-ember);
  --k-accent-soft: var(--k-ember-soft);

  /* Lines and glass */
  --k-line: rgba(255, 255, 255, 0.09);
  --k-line-strong: rgba(255, 255, 255, 0.16);
  --k-glass: linear-gradient(160deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.012));

  /* Type — Poppins carries the entire site. Hierarchy comes from weight,
     size and tracking rather than from a second family. */
  --k-font: 'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --k-fs-display: clamp(2.85rem, 8vw, 7rem);
  --k-fs-h1: clamp(2.3rem, 5.4vw, 4.5rem);
  --k-fs-h2: clamp(1.95rem, 3.9vw, 3.3rem);
  --k-fs-h3: clamp(1.28rem, 1.9vw, 1.7rem);
  --k-fs-h4: clamp(1.08rem, 1.3vw, 1.22rem);
  --k-fs-lead: clamp(1.05rem, 1.45vw, 1.28rem);
  --k-fs-body: 1.0625rem;
  --k-fs-sm: 0.9375rem;
  --k-fs-xs: 0.8125rem;
  --k-fs-label: 0.6875rem;

  /* Rhythm */
  --k-sec-y: clamp(5rem, 8vw, 8.5rem);
  --k-gap: clamp(1.25rem, 2vw, 2rem);
  --k-container: 1240px;
  --k-container-wide: 1480px;
  --k-pad-x: clamp(1.25rem, 4vw, 2.5rem);

  /* Form */
  --k-r-sm: 12px;
  --k-r-md: 18px;
  --k-r-lg: 26px;
  --k-r-xl: 34px;
  --k-r-pill: 999px;

  /* Depth */
  --k-shadow-card: 0 30px 80px -40px rgba(0, 0, 0, 0.9);
  --k-shadow-ember: 0 14px 44px -14px rgba(255, 45, 85, 0.7);
  --k-shadow-ember-hi: 0 14px 56px -12px rgba(255, 45, 85, 0.92);

  /* Motion */
  --k-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --k-ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --k-dur: 0.62s;

  /* Chrome */
  --k-header-h: 78px;
  --k-z-header: 9990;
}

/* ------------------------------------------------------- 2. Base and reset */

html {
  /* Anchor targets must clear the fixed header. */
  scroll-padding-top: calc(var(--k-header-h) + 1.25rem);
}

/* Do not inherit this from the parent theme. Divi happens to set border-box
   globally, but relying on that means a width:100% input with padding
   overflows its grid column the moment these styles are used anywhere else. */
body.ketnal,
body.ketnal *,
body.ketnal *::before,
body.ketnal *::after {
  box-sizing: border-box;
}

/* The hidden attribute is only display:none in the UA stylesheet, so any
   author rule that sets display — .k-btn is inline-flex — silently defeats it.
   The motion engine uses [hidden] to hide filtered items and the domain
   result button, so it has to actually hide them. */
body.ketnal [hidden] { display: none !important; }

body.ketnal {
  background: var(--k-ink-950);
  color: var(--k-chalk);
  font-family: var(--k-font);
  font-size: var(--k-fs-body);
  font-weight: 400;
  line-height: 1.65;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* clip, not hidden: overflow:hidden on an ancestor silently kills every
     position:sticky descendant, which this design depends on. */
  overflow-x: clip;
}

body.ketnal ::selection {
  background: rgba(255, 45, 85, 0.32);
  color: #fff0f3;
}

body.ketnal * {
  -webkit-tap-highlight-color: rgba(255, 45, 85, 0.18);
}

/* Filmic grain over the whole page. One fixed layer, no per-section cost. */
body.ketnal::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 220 220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

body.ketnal ::-webkit-scrollbar { width: 10px; height: 10px; }
body.ketnal ::-webkit-scrollbar-track { background: var(--k-ink-950); }
body.ketnal ::-webkit-scrollbar-thumb {
  background: linear-gradient(var(--k-ink-600), var(--k-ember-deep));
  border-radius: var(--k-r-pill);
  border: 2px solid var(--k-ink-950);
}

.k-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100000;
  padding: 0.9rem 1.4rem;
  background: var(--k-ember);
  color: #fff;
  font-weight: 600;
  border-radius: 0 0 var(--k-r-sm) 0;
}
.k-skip:focus { left: 0; }

/* --------------------------------------------- 3. Divi structural overrides
   Every layout section is: et_pb_section > et_pb_row > column > et_pb_code.
   Divi pads all three. We take that padding back so section HTML controls
   its own rhythm, and so full-bleed backgrounds actually reach the edges. */

body.ketnal #page-container,
body.ketnal #et-main-area,
body.ketnal #main-content { background: transparent; }

body.ketnal .et_pb_section.k-sec-wrap {
  padding: 0 !important;
  margin: 0 !important;
  background: transparent;
  overflow: visible;
}

body.ketnal .et_pb_row.k-row-wrap {
  width: 100% !important;
  max-width: 100% !important;
  padding: 0 !important;
  margin: 0 !important;
}

body.ketnal .k-row-wrap .et_pb_column {
  padding: 0 !important;
  margin: 0 !important;
  width: 100% !important;
  float: none;
}

body.ketnal .et_pb_code.k-code,
body.ketnal .k-code .et_pb_code_inner {
  padding: 0 !important;
  margin: 0 !important;
}

/* Divi's Theme Builder header wrapper. Fixed rather than sticky: a TB header
   sits in its own layout wrapper, and fixed is the only positioning that
   survives every Divi layout mode without the header being clipped. */
body.ketnal .et-l--header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--k-z-header);
  pointer-events: none;
}
body.ketnal .et-l--header .k-header { pointer-events: auto; }

/* Divi injects a top bar/nav we are replacing entirely. */
body.ketnal #main-header,
body.ketnal #top-header,
body.ketnal .et_pb_menu--style-inline_centered_logo #main-header { display: none !important; }

body.ketnal #main-content .container::before { display: none; }

/* ---------------------------------------------------------- 4. Typography */

/* ------------------------------------------------------------ BASE LAYER

   Specificity here is deliberately tuned to exactly (0,1,0): one class, via
   `.ketnal`, with every element selector neutralised inside :where().

   Why that exact number:
     - It beats every bare element selector Divi ships (`h1`, `p`, `img` — all
       (0,0,1)), so our reset still wins against the parent theme.
     - It loses to any single-class component rule in ketnal-sections.css, so
       `.k-brand img { height: 44px }` or `.k-plan__cta { margin-top: auto }`
       just work, with no !important and no specificity arms race.

   Getting this wrong is not theoretical. At (0,1,1) — the obvious
   `body.ketnal p` form — this block silently beat `.k-goal h3` and painted the
   light section's headings near-white on cream, overrode the header logo's
   height so the mark rendered six times too large, and killed `margin-top:auto`
   on the pricing buttons so they refused to align. Keep it at one class.
   ---------------------------------------------------------------------- */

.ketnal :where(h1, h2, h3, h4, h5, h6) {
  font-family: var(--k-font);
  color: var(--k-chalk);
  padding: 0;
  margin: 0;
  font-weight: 600;
}

.k-display {
  font-size: var(--k-fs-display);
  font-weight: 600;
  /* 1.0, not 0.95. Poppins descends ~0.21em below the baseline and its caps
     reach ~0.70em above it, so a line ending in a descender needs ~0.91em of
     room before its tail collides with the caps on the line beneath. Tight
     display leading is worth having; clipped or colliding glyphs are not. */
  line-height: 1;
  letter-spacing: -0.038em;
}

.k-h1 {
  font-size: var(--k-fs-h1);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.032em;
}

.k-h2 {
  font-size: var(--k-fs-h2);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.028em;
}

.k-h3 {
  font-size: var(--k-fs-h3);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.k-h4 {
  font-size: var(--k-fs-h4);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.012em;
}

.k-lead {
  font-size: var(--k-fs-lead);
  line-height: 1.6;
  color: var(--k-faint);
  font-weight: 300;
}

.k-body { font-size: var(--k-fs-body); color: var(--k-mute); }
.k-sm { font-size: var(--k-fs-sm); color: var(--k-mute); }
.k-xs { font-size: var(--k-fs-xs); color: var(--k-mute); }

/* The one place a second "family" appears is a tracked-out label. Same
   Poppins, treated as a different instrument. */
.k-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--k-fs-label);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  color: var(--k-accent-soft);
  line-height: 1;
}

.k-eyebrow--muted { color: var(--k-mute); }

.k-eyebrow__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--k-accent);
  box-shadow: 0 0 12px var(--k-accent);
  flex: none;
}

.k-num {
  font-size: var(--k-fs-label);
  font-weight: 500;
  letter-spacing: 0.24em;
  color: var(--k-faint);
  font-variant-numeric: tabular-nums;
}

/* Gradient ink, reserved for the accent word in a headline.

   font-style is pinned to normal so the rule renders correctly whichever
   element carries it. Earlier layouts marked this word up as <em>, which is
   italic by default, and depended on a separate class to cancel that. A theme
   update should never depend on the page layout in the database being updated
   in the same breath. */
.k-grad {
  font-style: normal;
  background: linear-gradient(102deg, #ffffff 0%, var(--k-ember-soft) 46%, var(--k-orchid-soft) 88%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.k-grad-ember {
  background: linear-gradient(102deg, #ff8a9f, var(--k-ember) 52%, var(--k-orchid));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Oversized backdrop wordmarks. */
.k-outline {
  color: transparent;
  -webkit-text-stroke: 1px rgba(255, 255, 255, 0.14);
}

.ketnal :where(p) { margin: 0 0 1.1em; padding: 0; }
.ketnal :where(p:last-child) { margin-bottom: 0; }

.ketnal :where(a) { color: inherit; text-decoration: none; }

/* height:auto here is a default, not a mandate: the header and footer logos
   set an explicit height and must be able to win. */
.ketnal :where(img, video) { max-width: 100%; height: auto; display: block; }

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

/* Form controls do not inherit font-family from their parent — a bare <button>
   falls back to the browser's Arial. Poppins is the only family on this site,
   so inheritance is forced here. */
.ketnal :where(button, input, select, textarea, optgroup) {
  font-family: inherit;
}

/* An inline <svg> with only a viewBox has no intrinsic size and falls back to
   300x150, which is how a 14px arrow ends up the size of a paragraph. Every
   unclassed icon therefore defaults to the current text size. Icons that need
   their own dimensions carry a class and set them explicitly. */
.ketnal :where(svg:not([class])) {
  width: 1em;
  height: 1em;
  flex: none;
}

/* Visible focus, always. The design is dark, so the ring is light and offset. */
body.ketnal :focus-visible {
  outline: 2px solid var(--k-ember-soft);
  outline-offset: 3px;
  border-radius: 4px;
}

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

/* ------------------------------------------------------------- 5. Layout */

.k-sec {
  position: relative;
  padding-block: var(--k-sec-y);
  isolation: isolate;
  /* Ambient .k-glow layers are deliberately positioned outside the section box.
     clip on one axis with visible on the other contains them horizontally
     without creating a scroll container, so position:sticky children — the
     service deck, the pinned rail — keep working. overflow:hidden here would
     break both. */
  overflow-x: clip;
  overflow-y: visible;
}

.k-sec--flush { padding-block: 0; }
.k-sec--tight { padding-block: clamp(3.5rem, 6vw, 6rem); }

.k-container {
  width: 100%;
  max-width: var(--k-container);
  margin-inline: auto;
  padding-inline: var(--k-pad-x);
}

.k-container--wide { max-width: var(--k-container-wide); }
.k-container--narrow { max-width: 820px; }

.k-hair {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg, transparent, var(--k-line-strong), transparent);
}

.k-glass {
  background: var(--k-glass);
  border: 1px solid var(--k-line);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
}

/* Section heading block, used on nearly every page. */
.k-head { max-width: 760px; }
.k-head--center { margin-inline: auto; text-align: center; }
.k-head .k-eyebrow { margin-bottom: 1.35rem; }
.k-head .k-h2 { margin-bottom: 1.1rem; }

.k-stack-sm > * + * { margin-top: 0.6rem; }
.k-stack > * + * { margin-top: 1.1rem; }
.k-stack-lg > * + * { margin-top: 2rem; }

.k-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.85rem;
}

.k-grid { display: grid; gap: var(--k-gap); }
.k-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.k-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.k-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1024px) {
  .k-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .k-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .k-grid--2,
  .k-grid--3,
  .k-grid--4 { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------ 6. Surfaces */

.k-card {
  position: relative;
  border-radius: var(--k-r-lg);
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.052), rgba(255, 255, 255, 0.014));
  border: 1px solid var(--k-line);
  box-shadow: var(--k-shadow-card);
  overflow: hidden;
  transition: border-color 0.4s var(--k-ease), background-color 0.4s var(--k-ease);
}

/* Cards may lift; they are not click targets in their own right where a
   button sits inside them. Hover lift is a 2px border-glow, not movement. */
.k-card:hover { border-color: var(--k-line-strong); }

.k-card__body { padding: clamp(1.5rem, 2.4vw, 2.25rem); }

/* A hairline that lights up from the accent on reveal. */
.k-rule {
  position: relative;
  height: 1px;
  background: var(--k-line);
  overflow: hidden;
}
.k-rule::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: scaleX(var(--p, 0));
  transform-origin: left;
  background: linear-gradient(90deg, var(--k-accent), var(--k-orchid));
}

.k-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.95rem;
  border-radius: var(--k-r-pill);
  border: 1px solid var(--k-line);
  background: rgba(255, 255, 255, 0.03);
  font-size: var(--k-fs-xs);
  font-weight: 500;
  color: var(--k-faint);
  letter-spacing: 0.01em;
}

.k-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.9rem 0.45rem 0.65rem;
  border-radius: var(--k-r-pill);
  border: 1px solid rgba(255, 45, 85, 0.35);
  background: rgba(255, 45, 85, 0.1);
  color: var(--k-ember-soft);
  font-size: var(--k-fs-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* ------------------------------------------------------------- 7. Buttons

   THE RULE: a button never changes position or size, in any state, ever.
   Only colour, border, shadow and filter are transitioned. Nothing here
   sets transform, translate, scale, padding or margin on :hover, :focus or
   :active — and nothing added later should either.                        */

.k-btn {
  --k-btn-bg: linear-gradient(102deg, #ff4d6d, var(--k-ember) 52%, var(--k-orchid));
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 1rem 1.85rem;
  border: 1px solid transparent;
  border-radius: var(--k-r-pill);
  background-image: var(--k-btn-bg);
  color: #fff;
  font-family: var(--k-font);
  font-size: var(--k-fs-sm);
  font-weight: 600;
  letter-spacing: 0.005em;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  box-shadow: var(--k-shadow-ember);
  transition:
    filter 0.3s var(--k-ease),
    box-shadow 0.3s var(--k-ease),
    border-color 0.3s var(--k-ease),
    background-color 0.3s var(--k-ease),
    color 0.3s var(--k-ease);
}

.k-btn:hover,
.k-btn:focus-visible {
  filter: brightness(1.09) saturate(1.05);
  box-shadow: var(--k-shadow-ember-hi);
}

.k-btn:active { filter: brightness(0.97); }

.k-btn[disabled],
.k-btn[aria-disabled='true'] {
  filter: grayscale(0.5) brightness(0.8);
  cursor: not-allowed;
  box-shadow: none;
}

.k-btn--ghost {
  background-image: none;
  background-color: rgba(255, 255, 255, 0.02);
  border-color: var(--k-line-strong);
  color: var(--k-chalk);
  box-shadow: none;
}
.k-btn--ghost:hover,
.k-btn--ghost:focus-visible {
  background-color: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.34);
  filter: none;
  box-shadow: none;
}

.k-btn--light {
  background-image: none;
  background-color: var(--k-bone);
  color: var(--k-ink-950);
  box-shadow: 0 14px 40px -18px rgba(244, 237, 227, 0.5);
}
.k-btn--light:hover,
.k-btn--light:focus-visible { background-color: #fff; filter: none; }

.k-btn--block { width: 100%; }
.k-btn--sm { padding: 0.7rem 1.25rem; font-size: var(--k-fs-xs); }
.k-btn--lg { padding: 1.15rem 2.2rem; font-size: var(--k-fs-body); }

.k-btn__icon { flex: none; width: 1em; height: 1em; }

/* Text link with an underline that grows. The link itself does not move. */
.k-link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 500;
  color: var(--k-chalk);
  background-image: linear-gradient(var(--k-accent), var(--k-accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 0.4s var(--k-ease), color 0.3s var(--k-ease);
  padding-bottom: 2px;
}
.k-link:hover,
.k-link:focus-visible { background-size: 100% 1px; color: #fff; }

/* --------------------------------------------------------- 8. Form fields */

.k-field { display: block; position: relative; }

.k-label {
  display: block;
  margin-bottom: 0.55rem;
  font-size: var(--k-fs-xs);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--k-faint);
}

.k-label__req { color: var(--k-ember); }

body.ketnal .k-input,
body.ketnal .k-select,
body.ketnal .k-textarea {
  width: 100%;
  padding: 0.95rem 1.15rem;
  border-radius: var(--k-r-sm);
  border: 1px solid var(--k-line);
  background: rgba(255, 255, 255, 0.028);
  color: var(--k-chalk);
  font-family: var(--k-font);
  font-size: var(--k-fs-sm);
  line-height: 1.5;
  transition: border-color 0.3s var(--k-ease), background-color 0.3s var(--k-ease), box-shadow 0.3s var(--k-ease);
  -webkit-appearance: none;
  appearance: none;
}

body.ketnal .k-textarea { min-height: 148px; resize: vertical; }

body.ketnal .k-select {
  /* Chevron drawn in the field so no icon font is needed. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23a99ba6' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1.1rem center;
  background-size: 12px 8px;
  padding-right: 2.75rem;
  cursor: pointer;
}
body.ketnal .k-select option { background: var(--k-ink-800); color: var(--k-chalk); }

body.ketnal .k-input::placeholder,
body.ketnal .k-textarea::placeholder { color: rgba(169, 155, 166, 0.6); }

body.ketnal .k-input:focus,
body.ketnal .k-select:focus,
body.ketnal .k-textarea:focus {
  outline: none;
  border-color: rgba(255, 45, 85, 0.55);
  background: rgba(255, 255, 255, 0.05);
  box-shadow: 0 0 0 4px rgba(255, 45, 85, 0.13);
}

/* Validation state is driven by JS setting aria-invalid, so the styling and
   the accessibility contract can never disagree. */
body.ketnal .k-input[aria-invalid='true'],
body.ketnal .k-select[aria-invalid='true'],
body.ketnal .k-textarea[aria-invalid='true'] {
  border-color: #ff5a72;
  background: rgba(255, 45, 85, 0.06);
}

.k-error {
  display: none;
  margin-top: 0.4rem;
  font-size: var(--k-fs-xs);
  color: #ff8095;
}
.k-error.is-shown { display: block; }

.k-check {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: var(--k-fs-xs);
  color: var(--k-mute);
  line-height: 1.55;
  cursor: pointer;
}
.k-check input {
  flex: none;
  width: 20px;
  height: 20px;
  margin: 1px 0 0;
  border-radius: 6px;
  border: 1px solid var(--k-line-strong);
  background: rgba(255, 255, 255, 0.03);
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: background-color 0.25s var(--k-ease), border-color 0.25s var(--k-ease);
}
.k-check input:checked {
  background-color: var(--k-ember);
  border-color: var(--k-ember);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m2.5 7.5 3 3 6-6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 13px;
}

/* The honeypot. Off-screen rather than display:none, because some bots skip
   fields that are explicitly hidden. */
.k-trap {
  position: absolute !important;
  left: -9999px !important;
  top: auto !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden;
}

.k-formnote {
  display: none;
  padding: 1rem 1.25rem;
  border-radius: var(--k-r-sm);
  font-size: var(--k-fs-sm);
  line-height: 1.55;
}
.k-formnote.is-shown { display: block; }
.k-formnote--ok {
  background: rgba(46, 204, 113, 0.1);
  border: 1px solid rgba(46, 204, 113, 0.34);
  color: #8ff0b5;
}
.k-formnote--bad {
  background: rgba(255, 45, 85, 0.1);
  border: 1px solid rgba(255, 45, 85, 0.34);
  color: #ff9bab;
}

/* ------------------------------------------------------- 9. Motion engine

   Reveal: JS adds .is-in once, via IntersectionObserver. Elements are never
   re-hidden, so nothing flickers when scrolling back up.
   Scroll-linked: JS writes --p (0 to 1) and CSS decides what to do with it,
   which keeps every transform off the JS thread.                          */

[data-k-reveal] {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition:
    opacity var(--k-dur) var(--k-ease),
    transform var(--k-dur) var(--k-ease);
  transition-delay: calc(var(--k-i, 0) * 90ms);
}

[data-k-reveal='fade'] { transform: none; }
[data-k-reveal='left'] { transform: translate3d(-32px, 0, 0); }
[data-k-reveal='right'] { transform: translate3d(32px, 0, 0); }
[data-k-reveal='scale'] { transform: scale(0.965); }

[data-k-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* Line-by-line headline reveal. Each line is a span inside an overflow-clip
   wrapper, so the text rises into view without shifting layout. */
/* Headline line breaks. Purely structural: one row per authored line so the
   break points are controlled rather than left to the container width.

   These rows used to rise into view from below, which required a mask to hide
   the incoming text — and that mask is what sliced the tails off descenders.
   Heading text is now static, so there is no mask and nothing to clip. */
.k-lines { display: block; }
.k-lines__row { display: block; }
.k-lines__row > span { display: block; }

/* Registered scroll-linked containers get --p written each frame. */
[data-k-scroll] { --p: 0; }

.k-parallax { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  body.ketnal *,
  body.ketnal *::before,
  body.ketnal *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  [data-k-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }

  /* Scroll-linked motion is switched off at the source: --p is pinned so
     every dependent transform resolves to its resting state. */
  [data-k-scroll] { --p: 0 !important; }
}

/* ------------------------------------------------------------ 10. Helpers */

.k-fill {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.k-abs { position: absolute; }
.k-rel { position: relative; }
.k-clip { overflow: hidden; }
.k-nosel { -webkit-user-select: none; user-select: none; }

.k-noscroll {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.k-noscroll::-webkit-scrollbar { display: none; }

/* Drag to scroll. The class is added by the motion engine so a region only
   advertises the grab cursor once the behaviour is actually wired up.
   Snapping and smooth scrolling are both switched off mid-drag: they fight
   direct scrollLeft manipulation and make the drag feel like it is sticking. */
.k-draggable { cursor: grab; }
.k-draggable.is-dragging {
  cursor: grabbing;
  scroll-behavior: auto;
  scroll-snap-type: none;
  -webkit-user-select: none;
  user-select: none;
}
.k-draggable.is-dragging a,
.k-draggable.is-dragging img { pointer-events: none; }

/* Ambient glow. Sized and placed by the section, coloured by --k-accent. */
.k-glow {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(90px);
  opacity: 0.5;
  background: radial-gradient(circle, var(--k-accent) 0%, transparent 68%);
  z-index: -1;
}

/* Cartographic grid for the studio-location card on the contact page, which
   stands in for an embedded map. It is deliberately NOT a general-purpose
   decorative background: a tiled hairline grid behind ordinary content reads as
   filler. The only consumer is .k-visit__art. */
.k-mesh {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  opacity: 0.42;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 74px 74px;
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 20%, transparent 78%);
  mask-image: radial-gradient(ellipse 80% 60% at 50% 40%, #000 20%, transparent 78%);
}

.k-hide-mobile { display: initial; }
.k-only-mobile { display: none; }

@media (max-width: 860px) {
  .k-hide-mobile { display: none !important; }
  .k-only-mobile { display: initial; }
}
