/*
 * Halif Hatch — Design Tokens
 * Single source of truth for frontend AND block editor.
 */

/* ---- Brand font: TT Hoves (Regular 400, DemiBold 600–800) ---- */
@font-face {
  font-family: "TT Hoves";
  src: url("../assets/fonts/TTHoves-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "TT Hoves";
  src: url("../assets/fonts/TTHoves-DemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---- Color — brand ---- */
  --color-brand: #FF7555;
  /* orange */
  --color-brand-soft: #FF7555;
  /* lighter orange (primary btn on dark) */
  --color-ink: #2F3035;
  /* charcoal */
  --color-text: #2F3035;
  --color-text-muted: #2F3035;
  /* client spec 2026-08-05: paragraphs are full ink */
  --color-text-invert: #F2F2F2;
  --color-text-invert-muted: #B5B5B5;
  /* paragraphs on a dark section sit a step below the headline white */
  --color-text-on-dark: #F2F2F2;
  /* steps headline/text on dark bg */
  --color-green: #2F3035;
  /* FAQ accordion question + answer */

  /* ---- Color — surfaces ---- */
  --color-bg-light: #eae8e8;
  --color-bg-white: #f7f7f7;
  --color-bg-dark: #404147;
  --color-bg-orange: var(--color-brand);
  --color-bg-pure-white: #ffffff;
  --color-on-black: #F9F9F9;
  /* black (Halif) header: menu text color */
  --color-dept-dock: #34C3BC;
  --color-dept-link: #9E917F;
  /* department brand colors (department pills + section backgrounds) */
  --color-header-bg: #2F3035;
  /* the one header bar surface — same charcoal as the footer (client,
     2026-08-20). The bar no longer recolors per department; the three
     department pills carry the brand colors instead. */

  /* ---- Color — lines / details ---- */
  --color-rule: #2F3035;
  --color-rule-soft: #d8d4d1;
  --color-lead-light: #EAE8E8;
  /* lead line (heading rule, text dash) on the orange context —
     the brand orange it uses elsewhere would vanish on an orange section
     (client spec 2026-08-09) */
  --color-mark: #e3e0dd;
  /* highlight behind text */
  --color-heading-mark: var(--color-ink);
  /* heading highlight — the 2px underline a marked word in halif/heading
     gets instead of the background fill; #2F3035 (client correction
     2026-08-14, was #F9F9F9) */
  --color-error: #D94A2F;
  /* invalid fields + validation messages — a deeper, more saturated sibling of
     the brand orange (same red-orange hue family) so it reads as "wrong"
     without importing a foreign red. Provisional until Figma. */
  --color-focus: var(--color-bg-dark);
  /* keyboard/focus ring — the theme's charcoal grey (#404147). Deliberately
     NOT orange and NOT red: orange is "chosen/active" (checked box, required *,
     stepper fill) and red is "invalid", so focus needs its own neutral.
     Contexts dark enough to swallow it override --ctx-focus. */
  --focus-ring-w: 2px;
  --focus-ring-offset: 2px;

  /* Back-compat aliases (older placeholder names) */
  --color-bg: var(--color-bg-white);

  /* ---- Typography ---- */
  --font-body: "TT Hoves", "Helvetica Neue", Arial, sans-serif;
  --font-heading: var(--font-body);

  --text-display-xl: 4rem;
  /* 64px — H1, client spec 2026-08-09 */
  --text-display-h2: 4rem;
  /* 64px — H2, client spec 2026-08-05 */
  --text-display-md: 2.625rem;
  /* 42px — H3 "Medium (sub)", client spec 2026-08-09 */
  --text-display-sm: 2rem;
  /* 32px — H4 "Small", client spec 2026-08-21; mobile value not given yet */
  --text-h3: clamp(1.5rem, 2.2vw, 2rem);
  --text-faq: var(--text-base);
  /* 26px — FAQ question AND answer */
  --text-step: 1.5rem;
  /* 24px — steps headline */
  --text-body-lg: 1rem;
  /* 16px — client 2026-08-20: everything that was 20px drops to 16px
     (header nav, pill buttons, footer meta, form group titles). Body
     paragraphs are --text-base and stay 20px. */
  --text-base: 1.25rem;
  /* 20px body/paragraph text — halif/text "Default" */
  --text-body-small: 1rem;
  /* 16px — halif/text "Small", client spec 2026-08-09 */
  --text-body-big: 1.5rem;
  /* 24px — halif/text "Big" (was 32px; client spec 2026-08-21) */
  --text-body-huge: 3rem;
  /* 48px — halif/text "Huge", client spec 2026-08-21 */
  --text-sm: 0.9375rem;
  --text-cookie: 0.8125rem;
  /* 13px — cookie bar paragraphs only, smaller than any block text */
  --text-lg: var(--text-body-lg);
  /* back-compat */
  /* back-compat */

  --leading-tight: 1.1;
  --leading-snug: 1.25;
  --leading-normal: 1.5;
  /* 30px at 20px body size */
  --leading-body-small: 1.625rem;
  /* 26px at 16px — halif/text "Small" */
  --leading-body-big: 2.25rem;
  /* 36px at 24px — halif/text "Big" (was 42px at 32px; client 2026-08-21) */
  --leading-body-huge: 3.625rem;
  /* 58px at 48px — halif/text "Huge" */
  --leading-display-xl: 4.375rem;
  /* 70px — H1 */
  --leading-display-h2: 4.375rem;
  /* 70px — H2 */
  --leading-display-md: 3.25rem;
  /* 52px — H3 "Medium (sub)", client spec 2026-08-09 */
  --leading-display-sm: 4.375rem;
  /* 70px at 32px — H4, client spec 2026-08-21 */
  --leading-faq: var(--leading-normal);
  /* 32px — FAQ question/answer */
  --leading-step: 2rem;
  /* 32px — steps headline */
  --text-step-text: var(--text-base);
  --leading-step-text: var(--leading-normal);
  /* steps body text — follows the body scale at every breakpoint; kept as
     dedicated tokens so it can diverge again if the client asks */

  --tracking-body: 0.03em;
  /* 3% letter spacing on text blocks */

  /* ---- Spacing scale ---- */
  --space-xs: 0.5rem;
  --space-s: 1rem;
  --space-m: 2rem;
  --space-l: 4rem;
  --space-xl: 8rem;




  /* ---- Section vertical spacing scale ---- */
  --section-pad-desktop-top: 168px;
  /* Medium is 150px (client spec 2026-08-21, was a provisional 134px);
     small is the value that used to be "medium". */
  --section-pad-desktop-top-md: 150px;
  --section-pad-desktop-top-sm: 100px;

  /* Bottom, client spec 2026-08-21: big 160 / middle 124 / small 110, and
     small is the block default. Token names keep the old -xl/-/-sm shape. */
  --section-pad-desktop-bottom-xl: 160px;
  --section-pad-desktop-bottom: 124px;
  --section-pad-desktop-bottom-sm: 110px;

  /* Tablet — placeholders mirroring desktop until Figma values land */
  --section-pad-tablet-top: var(--section-pad-desktop-top);
  --section-pad-tablet-top-md: var(--section-pad-desktop-top-md);
  --section-pad-tablet-top-sm: var(--section-pad-desktop-top-sm);
  --section-pad-tablet-bottom-xl: var(--section-pad-desktop-bottom-xl);
  --section-pad-tablet-bottom: var(--section-pad-desktop-bottom);
  --section-pad-tablet-bottom-sm: var(--section-pad-desktop-bottom-sm);

  /* Mobile — client-specified 2026-08-10 (top and bottom, all sizes) */
  /* Retuned 2026-08-21: the old values (108/90/74 - 124/98/82) were a
     straight scale of the desktop steps, so two ordinary neighbouring
     sections put 172px of nothing between them — 46% of a 375px frame,
     against 20% of a 1440 one. Vertical air does not scale with width; a
     phone reads a section break at roughly half what a desktop needs. */
  --section-pad-mobile-top: 88px;
  --section-pad-mobile-top-md: 72px;
  --section-pad-mobile-top-sm: 56px;
  --section-pad-mobile-bottom-xl: 96px;
  --section-pad-mobile-bottom: 76px;
  --section-pad-mobile-bottom-sm: 60px;

  /* Resolved per breakpoint (see @media overrides below) — blocks use these */
  --section-pad-top: var(--section-pad-desktop-top);
  --section-pad-top-md: var(--section-pad-desktop-top-md);
  --section-pad-top-sm: var(--section-pad-desktop-top-sm);
  --section-pad-bottom-xl: var(--section-pad-desktop-bottom-xl);
  --section-pad-bottom: var(--section-pad-desktop-bottom);
  --section-pad-bottom-sm: var(--section-pad-desktop-bottom-sm);

  /* halif/columns — optional vertical breathing room inside each column
     (client spec 2026-08-21); off by default, the block has no spacing.
     Steps down per breakpoint (see @media overrides below). */
  --columns-vspace: 36px;
  --columns-vspace-tablet: 24px;
  --columns-vspace-mobile: 12px;

  /* ---- Layout ---- */
  --container-max: 1200px;
  /* content width, gutters sit outside (content-box) */
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --container-inset: max(var(--gutter), calc((100vw - var(--container-max)) / 2));
  /* distance from the viewport edge to the centered container's content edge —
     lets full-bleed panels align their content with .halif-section__inner */
  --logo-width: 126px;
  /* uploaded header logo cap (client, 2026-08-20); height follows */
  --logo-width-footer: 126px;
  /* uploaded footer logo width */
  --logos-grid-mobile-max: 200px;
  /* cap on a stacked logo (press / partners grids) once the columns stack ≤767px (client, 2026-08-28) */

  /* ---- Footer (design 2026-08-07) ---- */
  --footer-bg: var(--color-ink);
  /* footer surface — darker than the shared dark-section #404147 (client, 2026-08-14) */
  --footer-text: #F9F9F9;
  /* all footer copy — brighter than the dark-ctx body colour (client, 2026-08-21) */
  --footer-pad-top: 110px;
  --footer-pad-bottom: 64px;
  --footer-columns-to-bottom: 180px;
  /* column row → the separator above the bottom line */
  --footer-rule-color: #B5B5B5;
  --footer-rule-space: 46px;
  /* separator → the bottom credits line, its last line of text (client, 2026-08-21) */
  --footer-menu-gap: 14px;
  /* vertical gap between nav items */
  --footer-contact-title-space-top: 2px;
  --footer-contact-title-space-bottom: 26px;
  --footer-contact-gap: 10px;
  /* vertical gap between contact items */
  --text-footer-contact: 1.5rem;
  /* 24px — contact phone/e-mail lines */
  --text-footer-meta: var(--text-body-lg);
  /* 20px — contact label + legal menu links */
  --footer-stack-gap: var(--space-l);
  /* mobile only: gap between the stacked footer columns */
  --footer-socials-space-top: 64px;
  /* client spec: gap from the footer logo down to the social icon row */
  --footer-socials-gap: 20px;
  --footer-socials-size: 24px;
  /* icon row metrics — provisional until the Figma footer frame is measured */
  --footer-socials-hover-opacity: 0.65;
  /* post-share (news/event detail): each icon carries this inner padding so the
     white box needs no padding of its own and the icons need no gap between
     them — the padding is the spacing. Provisional until a Figma frame lands. */
  --post-share-icon-pad: 12px;
  --leading-footer: 2rem;
  /* 32px — footer menu, contact title and contact lines */

  /* ---- Header ---- */
  --header-height: 100px;
  /* one fixed height — the bar no longer shrinks on scroll (client,
     2026-08-20), so there is no second set of scrolled metrics */
  --header-container-max: 1440px;
  /* header container incl. gutters */
  --header-gutter: 60px;

  /* Department subheader — the brand bar flush under the header on the
     Hatch / Dock / Link page templates (halif/subheader). Client-specified:
     60px tall, 80px logo. No mobile scale yet — it is designed together with
     the mobile header. */
  --subheader-height: 60px;
  /* the logo sits in a box exactly as wide as the header logo above it, so
     the two line up; inside it the department logo is right-aligned at a
     fixed 16px height with its own natural width, and a 2px rule fills the
     leftover space from the container's left edge up to --subheader-rule-gap
     before the logo. In the burger sheet the logo keeps that exact size and
     the rule is prepended at a fixed 30px (client, 2026-08-21) instead of
     filling a leftover it no longer has. */
  --subheader-logo-width: 80px;
  --subheader-logo-height: 16px;
  --subheader-rule-gap: 12px;
  /* the per-page CTA is always this size in the bar, whatever its label
     (client, 2026-08-21) — narrower and shorter than a section button, so
     it does not overpower the 60px bar. Fixed width, not a min-width: a
     long label ellipsises rather than stretching the bar's balance. */
  --subheader-btn-height: 40px;
  --subheader-btn-width: 195px;
  /* Section menu — the page's own sections, in the middle of the bar
     (client, 2026-08-21): 16/46px demibold ink, 52px between items and 52px
     from the logo box, underlined on the section being read. Ink rather than
     --ctx-text: the label reads as the bar's own type on all three brand
     colours, like the 2px rule beside the logo. */
  --subheader-nav-gap: 52px;
  --subheader-nav-item-gap: 40px;
  /* gap between the section links (client, 2026-08-21) */
  --subheader-nav-size: var(--text-body-lg);
  --subheader-nav-line-height: 46px;
  --subheader-nav-color: var(--color-ink);
  --subheader-nav-underline: 2px;
  /* ≤767px the bar is not a bar: it becomes the coloured panel filling the
     bottom of the burger sheet (client, 2026-08-21), where it is sized by
     its own padding instead of a fixed height. Provisional with the rest
     of the mobile header. */
  --subheader-sheet-pad-y: 28px;
  --subheader-sheet-gap: 20px;
  /* the section menu rides into the sheet with the logo and the CTA
     (client, 2026-08-21), stacked instead of the bar's scrolling row */
  --subheader-sheet-nav-gap: 12px;
  --subheader-sheet-nav-size: 1rem;
  --subheader-sheet-nav-leading: 1.5rem;
  /* the rule beside the logo is a fixed stub in the sheet — there is no
     header-logo box left to fill out to (client, 2026-08-21) */
  --subheader-sheet-rule-width: 30px;
  --nav-line-height: 46px;
  --nav-gap: 52px;

  /* Department pills (Hatch / Dock / Link) — the `departments` menu
     rendered as outline pills beside the logo. The pill wearing the
     current page's department is filled instead of outlined. Sizes are
     provisional until the Figma header frame is measured. */
  --dept-pill-height: 40px;
  /* border-box, so the 2px border is inside the 40px (client, 2026-08-21) */
  --dept-pill-width: 100px;
  /* fixed — all three pills are the same width regardless of label */
  --dept-pill-radius: 20px;
  --dept-pill-border: 2px;
  --dept-pill-gap: 20px;
  --dept-row-gap: 52px;
  /* logo → first pill (client, 2026-08-21) */
  --text-dept-pill: 1rem;

  /* Header language switcher — both languages are shown, the current one
     bright and the other muted, split by a hairline (client, 2026-08-21). */
  --lang-inactive: #656565;
  --lang-sep-gap: 10px;
  --lang-sep-width: 1px;
  --lang-sep-height: 16px;

  /* Burger sheet (≤1023px the nav collapses into a sheet under the bar).
     Sizes below are provisional until the Figma mobile frames are
     measured — only the 84px mobile logo is client-specified. */
  --burger-gap: 20px;
  /* switcher → burger, once the bar's structural flex gap was removed
     (2026-08-21). Provisional with the rest of the mobile bar. */
  --header-cta-gap: 10px;
  /* language switcher → the phone-only subheader CTA echoed into the bar
     (≤767px). Tight so the button hugs the switcher (client, 2026-08-28);
     matches the switcher's own 10px hairline rhythm. Provisional. */
  --burger-size: 48px;
  /* tap target */
  --burger-line-w: 45px;
  --burger-line-w-short: 36px;
  /* bottom line */
  --burger-line-h: 2px;
  --burger-line-gap: 10px;
  /* outer lines' centre offset: 2px line + 8px visual gap */
  --burger-line-scale: 1.25;
  /* short line → full length on the X morph (45 / 36) */
  --menu-sheet-text: 1.5rem;
  /* 24px — sheet menu items. Down from 36px (client, 2026-08-21): the
     sheet now carries the pill row, the menu AND the department panel
     with its section links, so the menu is one band among three rather
     than the whole sheet. */
  --menu-sheet-leading: 1.875rem;
  /* 30px */
  --menu-sheet-item-pad-top: 20px;
  /* divider → text */
  --menu-sheet-item-pad-bottom: 12px;
  /* text → divider */
  --menu-sheet-pad-top: 40px;
  /* CTA row's offset from the sheet bottom */

  /* Department pills inside the sheet (≤767px only — from 768px up they
     stay in the bar, desktop style, client 2026-08-21). The three pills
     share the sheet width evenly, so only the gap between them and the
     row's distance to the first menu item are stated here. */
  --menu-sheet-depts-gap: 36px;
  /* pill row → first menu item, and menu → department panel: the sheet's
     one structural gap, stated once as the flex container's gap */
  --menu-sheet-dept-pill-gap: 12px;

  /* ---- Radius / components ---- */
  --radius-m: 8px;

  /* ---- FAQ accordion ---- */
  /* accordion group width, centered */
  --faq-pad-block: 24px;
  /* question padding top/bottom */

  /* Optional live search box (halif/faq "Search box" toggle). No Figma yet —
     these mirror the form input treatment so the two read as one system;
     provisional until a design lands. */
  --faq-search-height: var(--form-input-h);
  --faq-search-radius: var(--form-input-radius);
  --faq-search-border: var(--form-input-border);
  --faq-search-border-color: var(--color-rule-soft);
  --faq-search-space-bottom: var(--space-m);
  --faq-search-pad-x: var(--space-s);
  --faq-search-gap: var(--space-xs);
  /* matched-word highlight: a soft brand tint, text colour untouched */
  --faq-highlight-bg: color-mix(in srgb, var(--color-brand) 24%, transparent);

  /* ---- Tabs ---- */
  --tabs-offset: 0px;
  /* whole tabs component left offset */

  /* ---- Slider ---- */
  --slider-dash-h: 3px;
  /* same line weight as the tabs underline */
  /* dashes split the pager-text width equally, so no width token */
  --slider-fade-ms: 250ms;
  /* incoming slide fade-in; view.js parses the number, keep the ms unit */
  --slider-fade-out-ms: 150ms;
  /* outgoing slide fade-out — asymmetric on purpose: exit quick, the
     entrance gets the beat; view.js parses this too */
  --slider-slide-ms: 400ms;
  /* push-slide travel when the animations toggle is on; view.js parses it */
  --slider-footer-space: 16px;
  /* dashes/pager/nav row offset from the tallest slide */
  --slider-dashes-space-bottom: 24px;
  /* dash bar → the pager number under it */
  --slider-rule-color: #B5B5B5;
  /* vertical divider between the slides in columns mode — same grey rule as
     the cards/list/pricing separators */
  --slider-num-line-w: 30px;
  --slider-num-line-h: 2px;
  --slider-num-w: 28px;
  /* nominal width of a column number at the H3 size ("1." measures 27.8px) —
     it is what centres the connector in the space between the digits and the
     headline. A nominal value on purpose: measuring each number would make the
     rule sit a few pixels differently in every column, and the number track is
     a fixed width for exactly that reason. */
  /* the rule that connects a column's number to its headline in columns mode
     (client, 2026-08-21) — it sits in the gutter between the number track and
     the content column, centred on the number's own line */
  --slider-number-offset: 80px;
  /* slide number gutter — how far left of the slides the number hangs */
  --slider-number-track: 32px;
  --slider-number-gap: var(--space-s);
  /* mobile number column + its gutter. Below 768px there is no 12-column grid
     to slice a number track out of (the .halif-w-* math starts at 768px), so
     the track is a fixed width instead — a max-content track would shift the
     content sideways every time the number changes width ("1." vs "2."). Wider
     numbers read into the gutter beside it, like the desktop track does.
     Provisional — no Figma mobile spec for the slider yet */

  /* ---- Steps ---- */
  --steps-visible: 3;
  /* steps per view — overridden per breakpoint below; the block's view.js
     reads this so CSS and JS always agree on the layout */
  --step-width: calc(3 * var(--grid-part) - var(--grid-gap));
  /* one step takes 4 grid parts (1/3 of the 12-col grid) and keeps the last
     part empty as its right spacing, so the text spans 3 columns. Fluid, not
     the old fixed 278px — that only matched the grid at the 1200px max width
     and drifted off it at every narrower desktop viewport. */
  --steps-gap: calc(var(--grid-part) + var(--grid-gap));
  /* the step's 1-part right spacing — together with --step-width this makes
     the 4-part stride */
  --step-top-gap: 28px;
  /* step content offset from the top line */
  --step-rule-space: 16px;
  /* gap above the rule under a step's headline */
  --steps-slide-ms: 400ms;
  /* track slide duration when the steps slider advances */
  --steps-nav-space: 32px;
  /* prev/next row offset from the tallest step (64px ≤767px) */
  --steps-space-top: 106px;
  /* client spec: gap above the steps slider (92px below 768px) */

  /* ---- List ---- */
  --list-num-indent: 8px;
  /* numbered style only — bullets and plain lists keep a 0 left edge */

  /* Checks style — the two-column ticked list (client spec 2026-08-21) */
  --list-check-row-h: 46px;
  /* one-line row height; taller rows grow, the rule stays at the bottom */
  --list-check-gap: 16px;
  /* tick → text */
  --list-check-col-gap: 30px;
  --list-check-space-bottom: 70px;
  /* the two-column ticked list ends further from what follows than an
     ordinary list does (client, 2026-08-21) */
  /* between the two columns */
  --list-check-size: 18px;
  /* tick width; the height follows the glyph's 18:16 aspect */
  --color-list-rule: #B5B5B5;
  /* the 1px line under every checked row */
  --list-check-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 16' fill='none'%3E%3Cpath d='M0.698242 8.58156L5.98885 13.7361C6.91634 14.6397 8.44496 14.4372 9.10511 13.3232L16.6982 0.509766' stroke='%23000' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* the tick itself — a mask, so --ctx-accent colors it. Geometry is the
     delivered assets/icons/check-list.svg verbatim (its baked-in #FF7555 is
     swapped for black because only the mask's alpha matters) */

  /* ---- Detail-page mark (the HALIF glyph atop news/event heroes) ---- */
  /* The delivered assets/uploads halif-icon.svg as a mask, so the four
     department colours (dark / halif orange / dock / link) come from
     background-color per the theme's "no baked fill on context icons" rule —
     one glyph, coloured in CSS. Fill swapped to black; only the alpha matters. */
  --mark-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 112 121'%3E%3Cpath d='M37.0521 0L0 105.271V121H19.1674L51.5265 25.9323H54.9381L87.3038 121H112L69.4191 0H37.0521Z' fill='%23000'/%3E%3C/svg%3E");
  --mark-size: 32px;
  /* w:32px, height follows the 112:121 glyph. The mark opens the white content
     section below the hero, bottom-aligned to the hero image's bleeding bottom
     edge — rendered by the lead blocks, see --lead-img-overhang below. */

  /* ---- Card (promo card: colored head + light body) ---- */
  /* head colors sampled from the Figma screenshot 2026-08-06 — refine with
     the variables export; orange reuses --color-bg-orange */
  /* the "blue" head option is the Dock brand color (client, 2026-08-14) */
  --card-glyph: #ffffff;
  /* lockup + icon on the colored head */
  --card-radius: 20px;
  --card-border: 1px solid #B5B5B5;
  /* radius + hairline outline, client spec 2026-08-21 */
  --card-pad-x: 30px;
  --card-top-h: 112px;
  /* logo + icon row: the 24px logo with 44px of air above and below it
     (client spec 2026-08-21). The head has no top padding of its own — this
     row is what holds the space. */
  --card-head-pad-bottom: 40px;
  /* the gap under the card title — written as the head's bottom padding, not
     the title's margin, so it cannot collapse out of the colored head */
  --card-title-gap: 38px;
  /* the title wraps within this width so it breaks the same way in every
     card, whatever the head's own width */
  --card-title-max: 290px;
  /* logo/icon row → title — client spec 2026-08-21 (was a screenshot-measured
     76px, back when the icon was pinned to the head's top edge) */
  --card-icon-w: 90px;
  --card-icon-h: 72px;
  /* left brand lockup — a rule, then the department's own logo from
     Appearance → Customize → Brand (client spec 2026-08-21). The text lockup
     below is the fallback for a department whose logo was never uploaded;
     weight is regular until a 300 face is delivered. */
  --card-brand-color: var(--color-on-black);
  --card-brand-line-w: 30px;
  --card-brand-line-h: 2px;
  --card-brand-line-color: #2F3035;
  --card-brand-gap: 16px;
  --card-logo-h: 24px;
  --text-card-brand: 2.125rem;
  /* 34px */
  --leading-card-brand: 2.5rem;
  /* 40px */
  --card-brand-tracking: 0.09em;
  /* 9% of the font size */
  --text-card-title: 2rem;
  /* 32px — client spec 2026-08-21 */
  --leading-card-title: 2.5rem;
  /* 40px */
  --card-body-pad-top: 30px;
  --card-body-pad-bottom: 48px;
  --text-card-small: 1rem;
  /* 16px — every paragraph after the card's lead text */
  --leading-card-small: 1.625rem;
  /* 26px */
  /* the rule between the card's content and its footer link — colour and both
     gaps are client-specified (2026-08-21) */
  --card-rule-color: #B5B5B5;
  --card-rule-space-top: 50px;
  /* content → rule */
  --card-rule-space-bottom: 30px;
  /* rule → button */
  --cards-pull-top: 90px;
  /* how far a halif/cards row (segment cards) hangs ABOVE its section, over
     the one before it, when "Overlap previous section" is on — the section
     before reserves exactly this much extra bottom padding for it. Client
     value 2026-08-21 (the pricing equivalent is 440px) */

  /* ---- Event card (halif/event-cards — image, title, date, place, more) ---- */
  /* values measured off the Figma screenshot 2026-08-06 — refine with the
     variables export */
  /* card surface is var(--ctx-card) — context-scoped, defined with the ctx
     rules below (a :root alias can't resolve it: custom properties substitute
     at the defining element, where no context exists yet) */
  --color-event-meta: #6E6F75;
  /* date/place lines + their icons — lighter than the card title */
  --event-card-media-ratio: 4 / 3;
  --event-card-pad-x: 30px;
  --event-card-pad-top: 30px;
  --event-card-pad-bottom: 34px;
  --text-event-card-title: 1.25rem;
  /* 20px */
  --leading-event-card-title: 1.75rem;
  /* 28px */
  --event-card-title-gap: 26px;
  /* title → meta list */
  --text-event-card-meta: 1rem;
  /* 16px */
  --leading-event-card-meta: 1.5rem;
  --event-card-meta-gap: 12px;
  /* between the date and place lines */
  --event-card-icon-size: 18px;
  /* news/event detail meta only: the icons sit half again card size on a
     circular disc in the hero's grey, so they carry the hero down into the white
     content section (client, 2026-08-29). Disc size provisional. */
  --detail-meta-icon-disc: 24px;
  --event-card-icon-gap: 22px;
  /* icon → its text */
  /* "Coming soon" line shown in place of the grid (inc/events.php switch) —
     deliberately subtle: the muted meta grey, body size, centered with room
     to breathe. No Figma for this state; values are provisional. */
  --event-cards-soon-color: var(--color-event-meta);
  --event-cards-soon-size: var(--text-base);
  --event-cards-soon-pad: var(--space-l);
  /* Same line for the news grid (inc/news.php switch) — identical treatment,
     its own names so the two states can diverge later. */
  --news-cards-soon-color: var(--event-cards-soon-color);
  --news-cards-soon-size: var(--event-cards-soon-size);
  --news-cards-soon-pad: var(--event-cards-soon-pad);

  /* ---- News card (halif/news-cards — image, tag chip, dept accent, title,
     excerpt) — values measured off the Figma screenshot 2026-08-07; refine
     with the variables export. Shares the event-card surface/radius/media
     ratio so the two grids read as one family. ---- */
  --news-card-pad-x: 30px;
  --news-card-pad-top: 30px;
  --news-card-pad-bottom: 40px;
  --news-card-accent-h: 6px;
  /* department color strip under the image */
  --text-news-card-title: 1.25rem;
  /* 20px */
  --leading-news-card-title: 1.75rem;
  /* 28px */
  --news-card-title-gap: 24px;
  /* title → excerpt */
  --text-news-card-excerpt: 1rem;
  --leading-news-card-excerpt: 1.5rem;
  --color-news-excerpt: #6E6F75;
  /* same muted grey as the event meta lines */
  --news-chip-inset: 14px;
  /* chip distance from the image corner */
  --news-chip-pad: 6px 18px;
  --text-news-chip: 1rem;
  --color-news-chip-bg: rgba(47 48 53 / 0.35);
  --color-news-chip-text: #ffffff;
  --cards-actions-gap: 64px;
  /* card grid → the centered "Show more" button below it */

  /* ---- Matchmaker card (halif/matchmaker-card — person photo with role chip,
     name, bio) — mirrors news-card tokens; square ratio for headshots. ---- */
  --matchmaker-card-media-ratio: 1 / 1;
  --matchmaker-card-pad-x: 30px;
  --matchmaker-card-pad-top: 24px;
  --matchmaker-card-pad-bottom: 32px;
  --text-matchmaker-name: 1.25rem;
  /* 20px */
  --leading-matchmaker-name: 1.75rem;
  /* 28px */
  --text-matchmaker-bio: 1rem;
  --leading-matchmaker-bio: 1.5rem;
  /* Below 1024px the matchmaker row becomes a peek slider (unlike the other
     card rows, which only slide under 768px): fixed-width cards so ~2 show at
     tablet width with a slice of the next, ~1 + peek on a phone. Matches the
     ~286px the desktop 3-up card lands at, so a card doesn't jump size when
     the slider engages. Invented — no mobile Figma. */
  --matchmaker-card-slide-w: 280px;
  /* Mobile card slider (under 768px a row of cards becomes one card per
     screen) — shared by the matchmaker, news and event card rows: the dots
     that replace prev/next. Colored by the page's department —
     --color-dept-current, with the brand orange as the plain-page fallback.
     Sizes are ours, not a Figma spec — no mobile design was delivered. */
  --card-slider-dot-size: 10px;
  --card-slider-dot-gap: 12px;
  --card-slider-dots-space: 24px;
  /* the prev/next controls beside the desktop slider's dots, at an end of
     the row: dimmed rather than hidden, so the dots stay centred */
  --card-slider-btn-disabled-opacity: 0.35;
  /* track → dots */
  /* How much of the next card the "peek" variant leaves on screen
     (halif/cards): the slide is one screen minus this and the grid gap, so
     the card after it shows past the right edge and says "swipe me". */
  --card-slider-peek: 40px;
  /* The widest a promo/segment card ever is on desktop — the 3-up grid card at
     container-max: (--container-max − two gaps) / 3. The gap is written as the
     literal desktop --grid-gap (32px, before its 16px mobile override) rather
     than var(--grid-gap), because this is read on the mobile slide where that
     token is already 16px — the value must stay the DESKTOP card width. Caps
     the mobile peek slide (shared/card-slider.css) so on a wide phone one card
     never stretches past its desktop size; the spare width shows more of the
     next card instead of inflating a single one. */
  --card-slide-max-w: calc((var(--container-max) - 2 * 32px) / 3);
  /* The width of one peek slide: a full screen minus the container inset, the
     peek and one grid gap, capped at the desktop card width. The `100%`
     resolves against the flex track at the point of use (custom properties
     substitute textually), so this is identical to the inline formula the
     halif/cards peek slide used to carry — now shared so the matchmaker and
     testimonial mobile sliders peek by exactly the same amount as the brand
     (halif/cards) slider and stay matched if the peek ever changes. */
  --card-peek-slide-w: min(
    calc(
      100% - var(--container-inset) - var(--card-slider-peek) - var(--grid-gap)
    ),
    var(--card-slide-max-w)
  );

  /* ---- Testimonial card (halif/testimonial-card — video testimonial:
     cover photo + play overlay + name + role, opens a video modal) ----
     Body type/padding reuse the matchmaker tokens. Everything below is the
     play overlay and the modal chrome — INVENTED, no Figma delivered. */
  --testimonial-card-media-ratio: 1 / 1;
  --testimonial-play-size: 76px;
  /* the play triangle: half-height + width, plus an optical nudge right so it
     sits centered inside the circle */
  --testimonial-play-triangle: 12px;
  --testimonial-play-triangle-w: 20px;
  --testimonial-play-triangle-nudge: 3px;
  /* the lightbox */
  --testimonial-modal-backdrop: rgba(31, 31, 33, 0.82);
  --testimonial-modal-pad: 20px;
  --testimonial-modal-max-w: 960px;
  --testimonial-modal-max-h: 82vh;
  --testimonial-modal-close-size: 44px;
  --testimonial-modal-close-offset: 52px;
  --testimonial-modal-close-glyph: 32px;
  --testimonial-modal-ms: 180ms;

  /* ---- "See on map" dialog (halif/event-lead — the embedded Google map the
     map button opens instead of a new tab) ---- INVENTED, no Figma; sized to
     match the testimonial lightbox so the two modals read as one thing. */
  --map-modal-backdrop: rgba(31, 31, 33, 0.82);
  --map-modal-pad: 20px;
  --map-modal-inner-pad: 16px;
  --map-modal-max-w: 900px;
  --map-modal-frame-h: 520px;
  --map-modal-close-size: 40px;
  --map-modal-close-glyph: 28px;
  --map-modal-ms: 180ms;

  /* ---- Pricing (halif/pricing — mode switcher + plan cards) ----
     Card and switcher values are the client spec of 2026-08-21; only the
     two spacing values around the switcher row are still screenshot-measured. */
  --pricing-pad-top: 68px;
  /* air inside the block above the switcher row (client, 2026-08-21) — it
     rides along with the pull, so it is the gap between the block's own top
     edge and its first row rather than section padding */
  --pricing-pull-top: 380px;
  /* the block hangs this far ABOVE its section, over the one before it, and
     the section before reserves exactly this much extra bottom padding for it
     (client, 2026-08-21; 246 → 310 → 440 → 380 the same day) */
  --pricing-switch-pad: 6px;
  /* track inset around the pill */
  --pricing-switch-h: 60px;
  --pricing-switch-w: 364px;
  /* the track is a fixed size, so the two modes are exact halves of it
     whatever their labels say (client, 2026-08-21) */
  --text-pricing-mode: var(--text-body-lg);
  --leading-pricing-mode: 3.125rem;
  /* 16/50 — taller than the 48px inner track on purpose, per the spec */
  --pricing-switch-space-top: 0px;
  /* block top edge → switcher row: none — the switcher sits right at the top
     of the 440px the block hangs above its section (client, 2026-08-21) */
  --pricing-switch-space-bottom: 98px;
  /* switcher row → card grid (client, 2026-08-21) */
  --pricing-grid-gap: 30px;
  /* horizontal gap between cards */
  --pricing-card-radius: 20px;
  --pricing-card-pad: 20px 20px 40px;
  /* client spec — 20px all round, 40px under the CTA */
  --pricing-card-border: #B5B5B5;
  --text-pricing-period: 1rem;
  /* 16px */
  --leading-pricing-period: 1.875rem;
  /* 30px */
  --pricing-period-tracking: 0.2em;
  --pricing-period-gap: 48px;
  /* period label → headline */
  --text-pricing-title: 1.25rem;
  /* 20px */
  --leading-pricing-title: 1.75rem;
  /* 28px */
  --pricing-title-gap: 8px;
  --text-pricing-desc: 1rem;
  --leading-pricing-desc: 1.5rem;
  --pricing-rule-space-top: 28px;
  --pricing-rule-space-bottom: 36px;
  --pricing-rule-color: #B5B5B5;
  --pricing-rule-color-featured: #656565;
  /* on the teal card */
  --text-pricing-amount: 2rem;
  /* 32px */
  --leading-pricing-amount: 1.75rem;
  /* 28px */
  --text-pricing-unit: 0.875rem;
  /* 14px — the currency sign and the /period both */
  --leading-pricing-unit: 1.875rem;
  /* 30px */
  --pricing-unit-tracking: 0.03em;
  --pricing-unit-rise: 2px;
  /* optical nudge above the price baseline box */
  --pricing-amount-gap: 4px;
  /* currency → amount → unit */
  --pricing-cta-space-top: 50px;

  /* ---- Form fields (client spec 2026-08-08 — text inputs / textareas) ---- */
  --form-input-h: 56px;
  --form-input-radius: 12px;
  /* client 2026-08-28: the 25px pill read as too round on a 56px field; a
     tighter corner sits better with the rest of the controls. The dropdown
     panel/rows/search and the upload zone all key off this family. */
  --form-input-pad-x: 34px;
  --form-input-border: 2px;
  --form-textarea-h: 225px;
  --form-textarea-h-short: 90px;
  /* short = character limit of 200 or less */
  --form-textarea-pad-y: 1rem;
  /* 16px — the textarea's own vertical inset. A single-line input centres its
     text on --form-input-h, but a textarea starts at the top edge, so it needs
     an explicit one. The character counter sits on this same inset and the
     reserved space at the bottom is derived from it — change it here and the
     counter follows. */
  --form-field-gap: 24px;
  /* field → field, vertically */
  --form-label-gap: 2px;
  /* label → hint → control: enough to read the hint as its own line, not
     enough to break the three apart into separate things */
  --form-hint-gap: 2px;
  /* label → its control */
  --form-legend-gap: 12px;
  /* option-group question → its first row of choices */
  --form-submit-width: 240px;
  /* the submit button is a primary button on a fixed width, not label-hugging */
  --form-nav-gap: 32px;
  /* The Back/Continue row sticks to the foot of the screen while a step is
     scrolled (see .halif-form__nav): this is the surface band above and below
     the buttons that scrolling content tucks behind, and the clearance from the
     screen edge while stuck. Inside a card the card gives its inner bottom inset
     back to this band (.is-card.is-stepped), so the band is not paid on top of
     the card padding at rest. */
  --form-nav-sticky-pad: 16px;
  /* Resting bottom inset of a stepped form card (.is-card.is-stepped). The
     sticky nav's own surface band is the main clearance; this is a small floor
     of air beneath it so the buttons don't sit flush on the card's edge. */
  --form-card-pad-bottom: 12px;
  /* Gap between the confirmation's headline and its paragraph, once the form
     is sent and the thank-you takes the card's place. */
  --form-success-title-gap: var(--space-s);
  /* Forward control while the step is unanswered. A muted fill rather than the
     primary pill at low opacity: translucency drops the label under a readable
     contrast, and a faded primary reads as a rendering fault where a flat grey
     reads as "not yet". Its own greys, not --color-bg-light, so the control
     stays visible on the light-grey section grounds too. */
  --form-nav-blocked-bg: #DCDBDB;
  --form-nav-blocked-text: #55565C;
  /* extra air on top of --form-field-gap between the last field of a step and
     the back/next row — the nav is chrome, not another field */
  --form-stepper-gap: 64px;
  /* extra air on top of --form-field-gap under the step indicator: 96px under
     the step NAMES. The heading below it has to group with the questions it
     owns, not with the chrome above it, so this gap is deliberately bigger
     than the one under the heading (--form-step-title-gap + --form-field-gap
     = 48px). Measured under the names because .halif-form__steps reserves
     their line itself (they are out of flow) and this sits on top of that. */
  --form-step-title-gap: var(--space-s);
  /* extra air on top of --form-field-gap under the step's own heading — at 32px
     it owns everything below it, so it can't sit on the same 32px rhythm that
     separates two sibling questions */
  --form-step-title-size: var(--text-display-md);
  /* The step's name is a real heading over its questions, so it takes the
     halif/heading H3 treatment whole — 42/52 desktop, 24/32 mobile (client
     spec 2026-08-20). At the old 32px it shared family, weight and colour with
     a 20px demibold question label and read as just another one. */
  --form-step-title-leading: var(--leading-display-md);
  /* pairs with --form-step-title-size — the H3 line box, 52px desktop /
     32px mobile */
  --form-group-title-size: var(--text-body-lg);
  /* 20px — a group inside a step: above the questions, below the step name */
  --form-group-gap: var(--space-s);
  /* extra air above a group that opens mid-step, on top of --form-field-gap */
  --text-step-name: var(--text-body-small);
  /* the name under a step marker — one step down from body, so it labels the
     marker without competing with the question the step is asking */
  --form-step-name-max: 11ch;
  /* names are single words by design; this only stops an over-long one from
     reaching its neighbours (it ellipsises — the full text is in the marker's
     accessible name either way) */

  --form-step-marker: 2rem;
  /* the numbered circle of a step — in the indicator, and again over that
     step's block in the summary, where it is what ties the two together */

  /* Desktop (≥1024px) the indicator is a rail beside the questions, not a bar
     above them: a vertical list reads as "where I am in a list of steps", and
     it stays in view while the step scrolls. */
  --form-rail-width: 240px;
  /* wide enough that every step name holds one line ("Team & commitment", the
     longest, is 147px against the 192px the name column gets) — the form sits
     in a 10-of-12 column now, so the width is there to spend */
  --form-rail-gap: var(--space-l);
  /* rail → questions */
  --form-rail-step-gap: 40px;
  /* marker → marker down the rail; the connector fills it */
  --form-rail-name-gap: var(--space-s);
  /* marker → its name, on the same line */
  --form-summary-col-gap: var(--space-l);
  /* review step (≥1200px): gutter between the recap's two answer columns once
     the steps rail has folded away and handed over its width */

  /* The summary step's per-answer "edit" control: the ghost pill of the nav
     buttons at a size that sits inside a row without outweighing the answer
     it belongs to. Same scale on mobile — it is already the small one. */
  --form-edit-height: 34px;
  --form-edit-pad-x: 18px;
  --form-edit-radius: 17px;

  /* The "why is Next closed" bubble over the step nav */
  --form-hint-pad-y: 8px;
  --form-hint-pad-x: 14px;
  --form-hint-radius: 12px;


  /* ---- Form controls (client spec 2026-08-08 — checkbox/radio items) ---- */
  --color-form-control-border: #b5b5b5;
  /* Boxes and markers were spec'd against a 20px option label; the label came
     down to 16px on 2026-08-28, so the whole control scales with it (~0.7).
     24px = --leading-form-option, so a control sits exactly on its label's
     line box — no nudging needed to centre it. */
  --form-control-size: 24px;
  --form-control-border: 2px;
  --form-control-radius: 7px;
  /* checkbox; radio is a circle */
  --form-option-gap: 12px;
  /* radio lists breathe more than checkbox columns (client spec 2026-08-08) */
  /* control → label, and between items */
  --form-dot-size: 12px;
  --form-check-tick-size: 14px;
  --form-tick-size: 21px;
  /* the dropdown's selected-row tick — sized off the row, not off a box */
  --text-form-option: 1rem;
  /* 16px — matches the question field label --text-body-lg (client 2026-08-28;
     was 20px per the 2026-08-08 spec) */
  --leading-form-option: 1.5rem;
  /* 24px = 16px × --leading-normal, so the option label shares the label's
     rhythm; still a length so the radio control's max(35px, …) stays 35px */
  --anim-check-ms: 220ms;
  /* tick draw / dot pop (enhancement layer) */

  /* ---- Switch (a single true/false question) ----
     The switch convention, not the checkbox one: a filled pill, no outline,
     white knob on a soft lift. Grey off / brand orange on keeps it in the
     form's palette. Provisional: no Figma frame for a switch yet — the track
     is sized off --form-control-size so it sits on the same row rhythm as the
     boxes beside it. */
  --form-switch-h: 32px;
  --form-switch-w: 58px;
  --form-switch-pad: 4px;
  --form-switch-knob: calc(var(--form-switch-h) - var(--form-switch-pad) * 2);
  /* how far the knob travels: the track minus the knob and both insets */
  --form-switch-travel: calc(
    var(--form-switch-w) - var(--form-switch-knob) - var(--form-switch-pad) * 2
  );
  --color-form-switch-track: #c9c5c1;
  /* one step darker than --color-rule-soft: as a filled shape it has to hold
     its own against the page, where a hairline does not */
  --color-form-switch-knob: #fff;
  --form-switch-knob-shadow: 0 1px 3px rgb(47 48 53 / 0.24);
  --anim-switch-ms: 200ms;
  /* knob travel — a touch quicker than the tick draw: a switch is a flip,
     not a stroke being drawn */
  --form-switch-press: 1.12;
  /* held-down stretch toward the side the knob is about to travel to */

  /* ---- Form select (dropdown) — provisional, no Figma frame yet.
     The closed control IS a text input (--form-input-*); only the panel,
     its rows and the in-panel search need their own values. ---- */
  --form-select-chevron-w: 16px;
  --form-select-chevron-h: 10px;
  /* same asset + size as the FAQ accordion arrow */
  --form-select-menu-offset: 8px;
  /* control → panel */
  --form-select-menu-radius: 12px;
  --form-select-menu-pad: 8px;
  --form-select-menu-max-h: 320px;
  /* 12px → a 48px row at the 16px/24px option type (--text-form-option); the
     rows read as a compact list under the 56px control rather than matching
     its height. */
  --form-select-option-pad-y: 12px;
  --form-select-option-pad-x: 26px;
  --form-select-option-radius: 8px;
  --form-select-search-h: 52px;
  --form-select-search-radius: 10px;
  /* Group delimiter inside the panel (the pinned countries → "All countries"
     boundary). The line is --color-rule-soft; the label reads at hint weight. */
  --form-select-divider-space: var(--space-xs);
  --color-form-select-surface: var(--color-bg-pure-white);
  --color-form-select-hover: var(--color-bg-light);
  --color-form-placeholder: var(--color-form-control-border);

  /* Help text under a label, and the line that explains an option or opens a
     step. Deliberately NOT the placeholder grey (#b5b5b5, 2.05:1 on white):
     this text has to be read to do its job, so it clears 4.5:1 (#6E6F75 is
     5.08:1) while still sitting a step back from the label above it. */
  --color-form-hint: #6E6F75;
  --shadow-form-select: 0 12px 32px rgba(47, 48, 53, 0.12);
  /* Cast upward by the sticky Next/Send/confirm bar while it is pinned to the
     foot of the screen, so a scrolled-past step reads as "more form continues
     behind this". Soft and shallow on purpose — a wayfinding cue, not a raised
     edge; it fades to nothing once the bar reaches its resting place. */
  --shadow-form-stickybar: 0 -6px 18px -8px rgba(47, 48, 53, 0.16);
  --anim-stickybar-ms: 220ms;
  --anim-select-ms: 180ms;
  /* panel open + chevron flip; close runs at --anim-select-close-ms */
  --anim-select-close-ms: 140ms;

  /* ---- Form upload (drop zone) — provisional, no Figma frame yet.
     Built on the text input's own radius and border weight so an upload
     question reads as the same family of control, only taller and dashed:
     the dashed edge is what says "you can drop something here", which a
     solid box does not. ---- */
  --form-upload-pad-y: 34px;
  --form-upload-pad-x: var(--form-input-pad-x);
  --form-upload-radius: var(--form-input-radius);
  --form-upload-border: var(--form-input-border);
  --form-upload-gap: 14px;
  /* icon → its two lines of text */
  --form-upload-icon: 32px;
  --form-upload-file-icon: 22px;
  /* the accepted file's card: a chip's softer radius, not a field's */
  --form-upload-file-pad-y: 14px;
  --form-upload-file-pad-x: 22px;
  --form-upload-file-radius: 10px;
  --form-upload-file-gap: 14px;
  --form-upload-remove: 32px;
  --form-upload-bar-h: 4px;
  --color-form-upload-tint: color-mix(
    in srgb,
    var(--color-brand) 7%,
    transparent
  );
  /* the file card's second line (its size): the placeholder grey is drawn
     for an empty control and looks washed out on a filled card */
  --color-form-upload-meta: color-mix(
    in srgb,
    var(--color-text) 62%,
    var(--color-bg-white)
  );
  --anim-upload-ms: 180ms;
  /* hover/drag state of the zone; the progress bar runs on --anim-bar-ms */

  /* ---- Heading bottom spacing (small/middle/big — adjust values here) ---- */
  /* client spec 2026-08-05: H1 24/48/86, H2 24/48/122 — only "big" differs */
  --heading-space-sm: 24px;
  --heading-space-sm-h1: 8px;
  /* H1 small — 8px, client spec 2026-08-21 */
  --heading-space-sm-h2: 8px;
  /* H2 (section lead) small — same 8px as H1, client spec 2026-08-21 */
  --heading-space-md-h2: 76px;
  /* H2 middle — client spec 2026-08-21 */
  --heading-space-sm-h3: 8px;
  --heading-space-md-h3: 16px;
  --heading-space-lg-h3: 28px;
  /* H3 has its own tight scale and no "extra large" — client spec 2026-08-21 */
  --heading-space-sm-h4: 8px;
  --heading-space-md-h4: 64px;
  /* H4: Middle (64) is the default; Small (8) added 2026-08-27 for the dense
     cookie policy — same tight step H1/H2/H3 use */
  --heading-space-md: 48px;
  --heading-space-lg: 86px;
  /* H1 big */
  --heading-space-lg-h2: 94px;
  /* H2 (section lead) big — 122→90 (2026-08-06), 90→94 (2026-08-21) */
  --heading-space-xl: 260px;
  /* extra large — requested for section leads, 2026-08-06; bumped 220→260, 2026-08-06 */

  /* ---- Text (paragraph) bottom spacing (small/middle/big/none) ---- */
  --text-space-sm: 16px;
  /* Big (is-size-large) paragraphs carry their own scale, and Huge a single
     step or none — client spec 2026-08-21 */
  --text-space-large-sm: 36px;
  --text-space-large-md: 64px;
  --text-space-large-lg: 90px;
  --text-space-huge-md: 100px;
  /* Huge paragraphs can also carry a top gap — the one "Big" step of the
     top-spacing control, None otherwise (client, 2026-08-21) */
  --text-space-top-huge-lg: 100px;
  --text-space-md: 32px;
  /* middle = default = body line-height */
  --text-space-lg: 80px;
  /* big — client, 2026-08-21 */

  /* ---- Text (paragraph) colour ---- */
  --text-subtle: #656565;
  /* "Subtle" option — fixed grey, same in every section context (client,
     2026-08-21). Default keeps the context body colour. */

  /* ---- Separator ---- */
  --separator-width: 60px;
  --separator-height: 2px;
  --separator-space: 32px;
  /* top & bottom of the brand separator — client spec 2026-08-21 (was 48px) */
  /* "line" variant (full-width hairline); its own spacing is still TBD in
     Figma, so it keeps the 48px it has been rendering at rather than
     following the brand line down */
  --separator-line-space: 48px;
  --separator-line-height: 1px;
  --separator-line-color: #b5b5b5;
  /* on the dock teal the #b5b5b5 hairline disappears — any non-brand
     separator sitting on a dock section/panel darkens to this instead */
  --separator-line-color-dock: #656565;
  /* "line-short" variant — same hairline, capped width, 50px above & below */
  --separator-line-short-width: 174px;
  --separator-line-short-space: 50px;

  /* ---- Buttons ---- */
  --btn-height: 50px;
  /* primary AND secondary, borders included */
  --btn-radius: 27px;
  --btn-pad-x-primary: 24.5px;
  --btn-pad-x-secondary: 29.5px;
  --btn-gap: 20px;
  /* gap inside a button group */
  --btn-row-space-top: var(--space-l);
  --btn-row-space-bottom: 0px;
  /* the air a .halif-btn-row keeps above and below itself — the bottom is 0
     on desktop because the row is nearly always the last thing in its
     section, where the section's own padding is the space (mobile differs) */
  --btn-primary-text: #ffffff;
  --text-btn: var(--text-body-lg);
  /* button label — swapped to the mobile scale below 768px */
  /* Disabled button — the "Coming soon" state (2026-08-27). A muted grey pill
     that reads as non-interactive on any surface, so it is a neutral value, not
     a context token. No Figma spec yet — provisional. */
  --btn-disabled-bg: var(--color-bg-light);
  --btn-disabled-text: #9a9a9a;
  /* External-link button — a small glyph pinned to the top-right of the label
     that marks a CTA leaving the site (opens in a new tab). It inherits the
     button's own text colour, softened, so it stays subtle on any surface. No
     Figma spec yet — provisional. */
  --btn-ext-size: 12px;
  --btn-ext-gap: 6px;
  --btn-ext-opacity: 0.6;
  --btn-ext-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M13%204h7v7M20%204l-9%209M18%2014v4a2%202%200%200%201-2%202H6a2%202%200%200%201-2-2V8a2%202%200%200%201%202-2h4'/%3E%3C/svg%3E");

  /* Download button — the same subtle after-glyph as the external one, but a
     tray-and-arrow, for a CTA that saves a file instead of navigating (the
     event "Add to calendar" .ics link). Shares the ext size/gap/opacity
     tokens so the two hints read as one family. Provisional — no Figma spec. */
  --btn-dl-icon: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M21%2015v4a2%202%200%200%201-2%202H5a2%202%200%200%201-2-2v-4M7%2010l5%205%205-5M12%2015V3'/%3E%3C/svg%3E");

  /* ---- Archive pagination (halif/news-cards, halif/event-cards) ----
     Small pill buttons for the page numbers — secondary (outline) for the
     other pages, primary (filled) for the current one, sharing the section's
     button context. No Figma spec — sizes are provisional. */
  --pagination-size: 40px;
  --pagination-pad-x: var(--space-xs);
  --pagination-radius: var(--btn-radius);
  --pagination-gap: var(--space-xs);

  /* ---- Newsletter (halif/newsletter — client spec 2026-08-21) ----
     One outlined pill with the button parked inside its right edge. The
     border and the button surface are fixed values, not context tokens: the
     row is the same object on a dark section as on a light one. Typed text
     still follows the context so it stays readable on both.
     No Figma frame yet beyond the sign-up row itself — only the values below
     marked "client spec" are given; the rest are derived. */
  --newsletter-max-width: 690px;
  --newsletter-height: 68px;
  /* client spec */
  --newsletter-radius: 25px;
  --newsletter-border: 2px;
  --color-newsletter-border: #b5b5b5;
  /* Text inset: the same one every text input in the theme uses, so the
     placeholder starts on the form's inset at both breakpoints. */
  --newsletter-pad-x: var(--form-input-pad-x);
  /* (68 - 50) / 2 — the button's inset from the pill edge, top/bottom/right */
  --newsletter-inset: calc((var(--newsletter-height) - var(--newsletter-btn-h)) / 2);
  --newsletter-btn-w: 144px;
  --newsletter-btn-pad-x: 0px;
  /* the given width is wide enough for the label on its own */
  --newsletter-btn-h: 50px;
  /* client spec */
  --newsletter-btn-text: 1rem;
  /* 16px, client spec — not --text-btn, which drops to the mobile scale */
  --color-newsletter-btn-bg: #f2f2f2;
  --color-newsletter-btn-text: var(--color-ink);
  /* typed text → the button chip */
  --newsletter-input-gap: var(--space-s);
  /* gap above the row (client spec 2026-08-21) */
  --newsletter-space-top: 82px;
  /* Sent state (no Figma — provisional). A rule sits above the confirmation,
     in the pill's own neutral so it reads on a dark or a light section; then
     the title, then a smaller, dimmed body. */
  --newsletter-status-gap: var(--space-s);
  --newsletter-status-rule-space: var(--space-m);
  --newsletter-status-rule-color: var(--color-newsletter-border);
  --newsletter-status-body-opacity: 0.7;

  /* ---- Cookie bar ---- */
  --cookie-bar-width: 420px;
  /* fixed card, bottom right — placeholder until Figma detail lands */
  --cookie-btn-height: 34px;
  --cookie-btn-pad-x: 16px;
  --cookie-btn-text: 0.875rem;
  /* 14px — temporary small accept button until Figma detail lands */

  /* Consent settings modal — all provisional, no Figma delivered. The
     switch mirrors the form switch dimensions (--form-switch-*). */
  --cookie-modal-max-w: 560px;
  --cookie-modal-radius: var(--radius-m);
  --cookie-overlay: rgb(0 0 0 / 0.5);
  --cookie-rule: rgb(47 48 53 / 0.15);
  --cookie-switch-w: 46px;
  --cookie-switch-h: 26px;
  --cookie-switch-pad: 3px;
  --cookie-switch-knob: calc(var(--cookie-switch-h) - var(--cookie-switch-pad) * 2);
  --cookie-switch-travel: calc(
    var(--cookie-switch-w) - var(--cookie-switch-knob) - var(--cookie-switch-pad) * 2
  );
  --cookie-switch-track: #c9c5c1;
  --cookie-switch-knob-bg: #fff;

  /* ---- Lead dash (paragraph text) ---- */
  --dash-lead-w: 60px;

  /* ---- Photo overlay (halif/overlay) ---- */
  --overlay-scrim: rgb(0 0 0 / 0.45);
  /* provisional — no Figma value for the scrim yet */

  /* ---- 12-column layout grid (Figma) ---- */
  --grid-gap: 32px;
  --grid-content-w: calc(100vw - 2 * var(--container-inset));
  /* the centered container's real content width at this viewport — the same
     100vw basis --container-inset uses, so both sides agree */
  --grid-part: calc((var(--grid-content-w) + var(--grid-gap)) / 12);
  /* one column + one gap = "one grid part" — what a grid offset counts in */
  --grid-col-w: calc(var(--grid-part) - var(--grid-gap));
  /* ≈ 70.67px once the container is at its 1200px max, fluid below it —
     Figma checks: FAQ 790 ≈ 8 cols, tabs offset 102 ≈ 1 col + gap */

  /* Lead line (halif/heading) — the heading text is pushed N grid parts in
     and the line fills that space minus the gutter. N per view: 4 desktop,
     3 tablet, 2 mobile (client instruction 2026-08-10); the gutter is the
     empty column before the text, 16px on mobile where a column is hairline. */
  --lead-offset: calc(4 * var(--grid-part));
  --lead-gutter: calc(var(--grid-col-w) + 2 * var(--grid-gap));
  --grid-guide-color: rgb(255 0 0 / 0.07);
  /* editor guide overlay columns */

  /* halif/breadcrumb — the news/event detail trail sits at the top of the white
     content section with its bottom on the line where the hero's featured image
     bleeds out below the grey hero. A fixed designed offset below that boundary
     (the reference image's bleed ≈ 80px), so the trail lands identically whether
     or not the post has an image — the image's real bottom varies with its
     aspect ratio and is deliberately not tracked here (deferred). Applied only
     ≥768px, where the image lives in its own right column. The gap from the
     breadcrumb band down to the article body is a fixed 32px (client spec). */
  --detail-breadcrumb-band: 80px;
  --detail-breadcrumb-gap: 48px;

  /* How far the hero's featured image bleeds below the grey section into the
     white content section (desktop). Shared by shared/lead.css (the image drop)
     and detail-meta (the mark's bottom sits on this same line). */
  --lead-img-overhang: calc(
    (var(--detail-breadcrumb-band) + var(--leading-body-small)) / 2
    + var(--card-radius)
  );

  /* ---- Motion (enhancement layer — rules scoped under body.halif-anim,
     see inc/animations.php; functional motion keeps its own tokens) ---- */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  /* switch knob: settles with a small overshoot, the spring every native
     switch has. Kept small enough that the knob never pokes past the track's
     inset (4px desktop / 3px mobile) at either end. */
  --ease-switch: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  /* iOS-style sheet/drawer travel (mobile menu) */
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  /* on-screen movement (content slider push) */
  --anim-reveal-ms: 500ms;
  /* scroll-reveal settle */
  --anim-reveal-load-ms: 560ms;
  /* load-time (hero) variant — same ease-out family as the scroll reveal,
     a touch more generous so the first screen reads as one cohesive system */
  --anim-check-stagger: 40ms;
  /* checked-list rows, per visual row. Tighter than the 60ms the card and
     column grids use: those stagger three items across, this walks five or
     more rows down, and 60ms would still be arriving after the eye has read
     to the bottom of the first column. */
  --anim-press-ms: 160ms;
  /* button hover/press feedback */
  --anim-bar-ms: 300ms;
  /* cookie bar enter/exit */
  --anim-photo-ms: 1200ms;
  /* photo panel settle (scale 1.05 → 1) during reveal */
  --anim-deco-ms: 1400ms;
  /* decoration trace (filled SVGs: outline + fill bloom) */
  --anim-deco-line-ms: 1800ms;
  /* lined decoration stroke draw — longer, calmer sweep */
  --anim-reduced-ms: 200ms;
  /* prefers-reduced-motion: what survives the kill-switch below as a plain
     fade — gentler, not gone (style.css, "Animations master toggle") */
  /* The whole stepper relay runs at half its original clock (client, 2026-08-29
     — "make the step transition 50% quicker"): every value below is halved from
     what it was, and the JS spark/advance timers (form/view.js) and the two
     hardcoded beats in style.css (digit-out, spark-pulse) were halved with them
     so the choreography keeps its shape, only faster. --anim-check-ms (the
     checkboxes' site-wide draw clock) is deliberately NOT touched — the tick
     borrows its own halved copy, --anim-step-check-ms, so checkboxes elsewhere
     keep their speed. */
  --anim-step-exit-ms: 75ms;
  /* stepped form: the old step's exit fade. Its real job is masking the
     instant scroll jump — the swap happens under it (form/view.js goTo) */
  --anim-step-in-ms: 200ms;
  /* stepped form: each head/question of the new step fading up */
  --anim-step-stagger: 20ms;
  /* stepped form: gap between those items — same clock as the checked list */
  --anim-step-check-ms: 110ms;
  /* relay: the tick's own draw duration — a halved copy of --anim-check-ms so
     the stepper speeds up without changing the checkboxes' draw everywhere */
  --anim-step-line-ms: 120ms;
  /* stepped form relay: the connector growing out of the finished marker.
     The tick before it draws on --anim-step-check-ms (its own halved clock) */
  --anim-step-fill-ms: 140ms;
  /* relay: the orange fill driving out of the ring you have finished and into
     the next one — the pricing amount's push (--slider-slide-ms), run on the
     marker, so a swap reads the same wherever the site does one */
  --anim-step-reveal-ms: 120ms;
  /* relay: the active (white) number sliding in over the arrived fill — the
     other half of the pricing-amount swap, run on the marker's digit so the
     ring's number reveals from the side the way a price does */
  --anim-step-reveal-lag: 60ms;
  /* relay: how long after the fill seats (--anim-step-ring-delay) the white
     number begins its reveal — the beat that reads as "the puck covers the old
     number, THEN the new one slides in" rather than the two riding in together */
  --anim-step-check-delay: 100ms;
  /* relay: the tick draws once the fill has driven clear of the ring (the
     fill leaves under the exit fade, so it is out at ~65ms past the flip) */
  --anim-step-line-delay: 120ms;
  /* relay: line leaves the marker on the same beat the tick starts drawing */
  --anim-step-ring-delay: 240ms;
  /* relay: the next fill arrives when the line does (line delay + travel) */
  --form-review-collapse-ms: 440ms;
  /* stepped form, review step (≥1200px): the steps rail folding its track
     away so the recap spreads into it — the track morph, one beat longer than
     the recap's own fade-up so the width settles just after it is readable */
  --form-review-fade-ms: 240ms;
  /* the rail's own fade as its track narrows — an exit, so shorter */

  /* ---- Breakpoints (reference — use in media queries) ---- */
  /* mobile < 768px | tablet 768–1023px | desktop >= 1024px */
}

html {
  box-sizing: border-box;
}

/* Decorations/photos bleed past the viewport edge on small screens;
   without a clip, mobile Chrome widens the layout viewport to fit them,
   which resizes every position:fixed surface (header, menu sheet, cookie
   bar). Clip the x axis only — `clip visible` keeps the vertical bleed
   (decorations hang above their section on purpose) and, unlike hidden,
   creates no scroll container. Fixed descendants are unaffected. */
.wp-site-blocks {
  overflow: clip visible;
}

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

/* =============================================================
   Color context system
   A section/panel carries `.halif-ctx` + `data-ctx="light|white|dark|orange|pure-white|dock|link"`.
   Child blocks NEVER pick colors — they read these variables only.
   ============================================================= */

.halif-ctx,
.halif-ctx[data-ctx="light"] {
  --ctx-surface: var(--color-bg-light);
  --ctx-text: var(--color-text);
  --ctx-body: var(--color-text-muted);
  --ctx-accent: var(--color-brand);
  --ctx-line: var(--color-brand);
  /* steps timeline */
  --ctx-lead: var(--color-brand);
  /* lead line in front of a heading/paragraph */
  --ctx-btn-bg: var(--color-ink);
  /* primary button */
  --ctx-btn-text: var(--btn-primary-text);
  --ctx-outline: var(--ctx-btn-bg);
  /* secondary button border always follows the primary fill */
  --ctx-mark: var(--color-mark);
  --ctx-rule: var(--color-rule);
  --ctx-sep-line: var(--separator-line-color);
  /* halif/separator "line" / "line-short" hairline */
  --ctx-step: var(--color-text);
  /* steps headline + text */
  --ctx-step-rule: var(--color-ink);
  /* the short hairline under a step's headline */
  --ctx-watermark: rgba(255 255 255 / 0.45);
  --ctx-card: var(--color-bg-white);
  /* event/news card surface — flips against the section bg: white cards on
     the grey section, grey cards on white sections */
}

.halif-ctx[data-ctx="white"] {
  --ctx-surface: var(--color-bg-white);
  --ctx-card: var(--color-bg-light);
}

.halif-ctx[data-ctx="pure-white"] {
  --ctx-surface: var(--color-bg-pure-white);
  --ctx-card: var(--color-bg-light);
}

.halif-ctx[data-ctx="dark"] {
  --ctx-focus: var(--color-text-invert);
  --ctx-surface: var(--color-bg-dark);
  --ctx-text: var(--color-text-invert);
  --ctx-body: var(--color-text-invert-muted);
  --ctx-line: var(--color-brand);
  --ctx-btn-bg: var(--color-brand-soft);
  --ctx-btn-text: var(--btn-primary-text);
  --ctx-mark: rgba(255 255 255 / 0.16);
  --ctx-rule: var(--color-text-invert);
  --ctx-step: var(--color-text-on-dark);
  --ctx-step-text: var(--color-text-invert-muted);
  --ctx-step-rule: var(--separator-line-color);
  --ctx-watermark: rgba(255 255 255 / 0.08);
}

.halif-ctx[data-ctx="orange"] {
  --ctx-surface: var(--color-bg-orange);
  --ctx-text: var(--color-text);
  --ctx-body: var(--color-text);
  /* client spec: full ink on orange */
  --ctx-line: #ffffff;
  --ctx-lead: var(--color-lead-light);
  --ctx-btn-bg: var(--color-ink);
  --ctx-btn-text: var(--btn-primary-text);
  --ctx-mark: rgba(255 255 255 / 0.35);
  --ctx-rule: var(--color-text);
  --ctx-watermark: rgba(255 255 255 / 0.85);
}

/* Department section colors: both are light enough to carry full ink, so
   they read like `orange` rather than like `dark`. Dock was light-text until
   2026-08-21 — that was written for the old deep green #007855; on the teal
   the client now uses (#34C3BC) headlines and body stay --color-ink
   (#2F3035), which is also what the header's dock menu already does. Link is
   a midtone taupe and has always been ink. */
.halif-ctx[data-ctx="dock"] {
  --ctx-surface: var(--color-dept-dock);
  --ctx-text: var(--color-text);
  --ctx-body: var(--color-text);
  --ctx-line: #ffffff;
  --ctx-btn-bg: var(--color-ink);
  --ctx-btn-text: var(--btn-primary-text);
  --ctx-mark: rgba(255 255 255 / 0.35);
  --ctx-rule: var(--color-text);
  --ctx-sep-line: var(--separator-line-color-dock);
  --ctx-watermark: rgba(255 255 255 / 0.85);
}

.halif-ctx[data-ctx="link"] {
  --ctx-surface: var(--color-dept-link);
  --ctx-text: var(--color-text);
  --ctx-body: var(--color-text);
  --ctx-line: #ffffff;
  --ctx-btn-bg: var(--color-ink);
  --ctx-btn-text: var(--btn-primary-text);
  --ctx-mark: rgba(255 255 255 / 0.35);
  --ctx-rule: var(--color-text);
  --ctx-watermark: rgba(255 255 255 / 0.85);
}

/* Current page's department color — the same color its header bar carries
   (inc/post-types/page.php sets the body class). Exposed as a token so a
   block can opt into it, e.g. halif/slider's "Department color number".
   Only the three non-default departments declare it: a plain Halif page has
   no brand color to take (its header is simply dark), so consumers read it
   as `var(--color-dept-current, <their normal ink>)` and stay unchanged
   there. */
body.halif-dept-hatch {
  --color-dept-current: var(--color-brand);
}

body.halif-dept-dock {
  --color-dept-current: var(--color-dept-dock);
}

body.halif-dept-link {
  --color-dept-current: var(--color-dept-link);
}

/* Detail-page department accent — set on single news/event pages
   (inc/post-types/news.php + events.php add `halif-detail-dept-*`). It colors
   the department-aware content blocks (the checks list tick, the short brand
   rule) with the article's department color — the same mapping the news hero
   mark and card strip use, so halif is the dark ink rather than orange. A
   separate hint from `halif-dept-*` above: detail pages have no subheader, so
   they must not take that class's top-padding reservation. Off a detail page
   `--detail-accent` is unset and consumers fall back to their normal accent. */
body.halif-detail-dept-halif {
  --detail-accent: var(--color-bg-dark);
}

body.halif-detail-dept-hatch {
  --detail-accent: var(--color-brand);
}

body.halif-detail-dept-dock {
  --detail-accent: var(--color-dept-dock);
}

body.halif-detail-dept-link {
  --detail-accent: var(--color-dept-link);
}

/* Per-device visibility — `is-hide-t` / `is-hide-m` on halif/section,
   halif/split-section and halif/split-panel (Visibility panel; no
   hide-on-desktop by design).
   Frontend: gone. Editor (device preview): dimmed but still selectable,
   which is why the editor rules restore each block's own display value.
   The panel rules instead exempt the editor from `display: none` up front
   (`:not(.editor-styles-wrapper *)`) — a panel's own display value varies
   (block / flex when spread), so there is nothing single to restore. */
@media (min-width: 768px) and (max-width: 1023px) {
  .halif-section.is-hide-t,
  .halif-split.is-hide-t {
    display: none;
  }

  .editor-styles-wrapper .halif-section.is-hide-t {
    display: block;
    opacity: 0.35;
  }

  .editor-styles-wrapper .halif-split.is-hide-t {
    display: grid;
    opacity: 0.35;
  }

  .halif-panel.is-hide-t:not(.editor-styles-wrapper *) {
    display: none;
  }

  /* the surviving panel takes the whole row instead of leaving its
     sibling's grid track empty */
  .halif-split:has(> .halif-panel.is-hide-t):not(.editor-styles-wrapper *) {
    grid-template-columns: 1fr;
  }

  /* …and the accent divider has nothing left to divide */
  .halif-split.has-divider:has(> .halif-panel.is-hide-t):not(.editor-styles-wrapper *)::after {
    display: none;
  }

  /* the surviving panel is the whole section now — it owes no half-gap to a
     seam that isn't there, so both sides fall back to the page inset */
  .halif-split:has(> .halif-panel.is-hide-t):not(.editor-styles-wrapper *) > .halif-panel:not(.is-photo) .halif-panel__inner {
    padding-left: calc(var(--container-inset) + var(--panel-indent));
    padding-right: calc(var(--container-inset) + var(--panel-indent));
  }

  .editor-styles-wrapper .halif-panel.is-hide-t {
    opacity: 0.35;
  }
}

@media (max-width: 767px) {
  .halif-section.is-hide-m,
  .halif-split.is-hide-m {
    display: none;
  }

  .editor-styles-wrapper .halif-section.is-hide-m {
    display: block;
    opacity: 0.35;
  }

  .editor-styles-wrapper .halif-split.is-hide-m {
    display: grid;
    opacity: 0.35;
  }

  .halif-panel.is-hide-m:not(.editor-styles-wrapper *) {
    display: none;
  }

  /* stacked already, so only the accent divider needs clearing */
  .halif-split.has-divider:has(> .halif-panel.is-hide-m):not(.editor-styles-wrapper *) > .halif-panel:first-child {
    border-bottom: 0;
  }

  .editor-styles-wrapper .halif-panel.is-hide-m {
    opacity: 0.35;
  }
}

/* Site-wide visibility — `is-hidden-site` on halif/section and
   halif/split-section ("Hide from visitors": Visibility panel / toolbar eye).
   Editor-only by construction: render.php outputs nothing when hidden, so
   the class never reaches the frontend. Dimmed like the per-device hides,
   plus a dashed outline and a corner badge so "hidden everywhere" can't be
   mistaken for a device-specific hide while previewing. */
.editor-styles-wrapper .halif-section.is-hidden-site,
.editor-styles-wrapper .halif-split.is-hidden-site {
  opacity: 0.45;
  outline: 1px dashed rgba(47, 48, 53, 0.45);
  outline-offset: -1px;
}

.editor-styles-wrapper .halif-section.is-hidden-site::before,
.editor-styles-wrapper .halif-split.is-hidden-site::before {
  content: "Hidden on site";
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 10;
  padding: 3px 10px;
  border-radius: 99px;
  background: var(--color-ink);
  color: var(--color-bg-light);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  pointer-events: none;
}

/* =============================================================
   Layout guard — halif sections are always full-bleed, even when
   a template renders post content inside a constrained layout.
   ============================================================= */

.halif-section,
.halif-split {
  width: 100vw;
  max-width: 100vw !important;
  margin-left: calc(50% - 50vw) !important;
  margin-right: calc(50% - 50vw) !important;
  /* kill the theme/editor block gap so sections touch each other */
  margin-block: 0 !important;
}

/* editor canvas: same escape, overriding the constrained-layout rules the
   editor injects with higher specificity. Margins must be re-asserted here
   too: core's constrained layout sets `margin-inline: auto !important` on
   container children, and inside the canvas those rules are injected after
   this stylesheet — only specificity (0-2-0 vs core's 0-1-0) wins there. */
.editor-styles-wrapper .is-root-container>.halif-section,
.editor-styles-wrapper .is-root-container>.halif-split,
.editor-styles-wrapper .block-editor-block-list__layout>.halif-section,
.editor-styles-wrapper .block-editor-block-list__layout>.halif-split {
  max-width: none !important;
  width: 100vw;
  margin-left: calc(50% - 50vw) !important;
  margin-right: calc(50% - 50vw) !important;
}

/* Editor parity: the canvas flow layout adds block-gap top margins inside
   InnerBlocks containers that the frontend markup never has — halif blocks
   space themselves with bottom margins only. */
.editor-styles-wrapper .halif-section__inner>.wp-block,
.editor-styles-wrapper .halif-panel__inner>.wp-block,
.editor-styles-wrapper .halif-faq>.wp-block,
.editor-styles-wrapper .halif-faq-item__answer>.wp-block,
.editor-styles-wrapper .halif-overlay>.wp-block,
.editor-styles-wrapper .halif-column>.wp-block {
  margin-block-start: 0;
}

/* =============================================================
   12-column layout grid
   Shared by any block that places content on the Figma grid.
   ============================================================= */

.halif-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
}

/* Spans — children of .halif-grid only. Longhand `grid-column-end: span n`
   so a span combines with an `is-start-*` class (the `grid-column` shorthand
   would reset the start and collapse the item to one column). Span 12 is a
   full-bleed row regardless of any inherited start. */
.halif-grid>.is-span-1 {
  grid-column-end: span 1;
}

.halif-grid>.is-span-2 {
  grid-column-end: span 2;
}

.halif-grid>.is-span-3 {
  grid-column-end: span 3;
}

.halif-grid>.is-span-4 {
  grid-column-end: span 4;
}

.halif-grid>.is-span-5 {
  grid-column-end: span 5;
}

.halif-grid>.is-span-6 {
  grid-column-end: span 6;
}

.halif-grid>.is-span-7 {
  grid-column-end: span 7;
}

.halif-grid>.is-span-8 {
  grid-column-end: span 8;
}

.halif-grid>.is-span-9 {
  grid-column-end: span 9;
}

.halif-grid>.is-span-10 {
  grid-column-end: span 10;
}

.halif-grid>.is-span-11 {
  grid-column-end: span 11;
}

.halif-grid>.is-span-12 {
  grid-column: 1 / -1;
}

/* Start column (1-based) — start 3 means 2 empty grid columns before */
.halif-grid>.is-start-1 {
  grid-column-start: 1;
}

.halif-grid>.is-start-2 {
  grid-column-start: 2;
}

.halif-grid>.is-start-3 {
  grid-column-start: 3;
}

.halif-grid>.is-start-4 {
  grid-column-start: 4;
}

.halif-grid>.is-start-5 {
  grid-column-start: 5;
}

.halif-grid>.is-start-6 {
  grid-column-start: 6;
}

.halif-grid>.is-start-7 {
  grid-column-start: 7;
}

.halif-grid>.is-start-8 {
  grid-column-start: 8;
}

.halif-grid>.is-start-9 {
  grid-column-start: 9;
}

.halif-grid>.is-start-10 {
  grid-column-start: 10;
}

.halif-grid>.is-start-11 {
  grid-column-start: 11;
}

.halif-grid>.is-start-12 {
  grid-column-start: 12;
}

/* Tablet overrides (≤1023px) — optional; without them desktop spans apply */
@media (max-width: 1023px) {
  .halif-grid>.is-span-t-1 {
    grid-column-end: span 1;
  }

  .halif-grid>.is-span-t-2 {
    grid-column-end: span 2;
  }

  .halif-grid>.is-span-t-3 {
    grid-column-end: span 3;
  }

  .halif-grid>.is-span-t-4 {
    grid-column-end: span 4;
  }

  .halif-grid>.is-span-t-5 {
    grid-column-end: span 5;
  }

  .halif-grid>.is-span-t-6 {
    grid-column-end: span 6;
  }

  .halif-grid>.is-span-t-7 {
    grid-column-end: span 7;
  }

  .halif-grid>.is-span-t-8 {
    grid-column-end: span 8;
  }

  .halif-grid>.is-span-t-9 {
    grid-column-end: span 9;
  }

  .halif-grid>.is-span-t-10 {
    grid-column-end: span 10;
  }

  .halif-grid>.is-span-t-11 {
    grid-column-end: span 11;
  }

  .halif-grid>.is-span-t-12 {
    grid-column: 1 / -1;
  }

  .halif-grid>.is-start-t-1 {
    grid-column-start: 1;
  }

  .halif-grid>.is-start-t-2 {
    grid-column-start: 2;
  }

  .halif-grid>.is-start-t-3 {
    grid-column-start: 3;
  }

  .halif-grid>.is-start-t-4 {
    grid-column-start: 4;
  }

  .halif-grid>.is-start-t-5 {
    grid-column-start: 5;
  }

  .halif-grid>.is-start-t-6 {
    grid-column-start: 6;
  }

  .halif-grid>.is-start-t-7 {
    grid-column-start: 7;
  }

  .halif-grid>.is-start-t-8 {
    grid-column-start: 8;
  }

  .halif-grid>.is-start-t-9 {
    grid-column-start: 9;
  }

  .halif-grid>.is-start-t-10 {
    grid-column-start: 10;
  }

  .halif-grid>.is-start-t-11 {
    grid-column-start: 11;
  }

  .halif-grid>.is-start-t-12 {
    grid-column-start: 12;
  }
}

/* Mobile overrides (≤767px) — halif/column defaults to span-m-12 = stacked */
@media (max-width: 767px) {
  .halif-grid>.is-span-m-1 {
    grid-column-end: span 1;
  }

  .halif-grid>.is-span-m-2 {
    grid-column-end: span 2;
  }

  .halif-grid>.is-span-m-3 {
    grid-column-end: span 3;
  }

  .halif-grid>.is-span-m-4 {
    grid-column-end: span 4;
  }

  .halif-grid>.is-span-m-5 {
    grid-column-end: span 5;
  }

  .halif-grid>.is-span-m-6 {
    grid-column-end: span 6;
  }

  .halif-grid>.is-span-m-7 {
    grid-column-end: span 7;
  }

  .halif-grid>.is-span-m-8 {
    grid-column-end: span 8;
  }

  .halif-grid>.is-span-m-9 {
    grid-column-end: span 9;
  }

  .halif-grid>.is-span-m-10 {
    grid-column-end: span 10;
  }

  .halif-grid>.is-span-m-11 {
    grid-column-end: span 11;
  }

  .halif-grid>.is-span-m-12 {
    grid-column: 1 / -1;
  }

  .halif-grid>.is-start-m-1 {
    grid-column-start: 1;
  }

  .halif-grid>.is-start-m-2 {
    grid-column-start: 2;
  }

  .halif-grid>.is-start-m-3 {
    grid-column-start: 3;
  }

  .halif-grid>.is-start-m-4 {
    grid-column-start: 4;
  }

  .halif-grid>.is-start-m-5 {
    grid-column-start: 5;
  }

  .halif-grid>.is-start-m-6 {
    grid-column-start: 6;
  }

  .halif-grid>.is-start-m-7 {
    grid-column-start: 7;
  }

  .halif-grid>.is-start-m-8 {
    grid-column-start: 8;
  }

  .halif-grid>.is-start-m-9 {
    grid-column-start: 9;
  }

  .halif-grid>.is-start-m-10 {
    grid-column-start: 10;
  }

  .halif-grid>.is-start-m-11 {
    grid-column-start: 11;
  }

  .halif-grid>.is-start-m-12 {
    grid-column-start: 12;
  }
}

/* Standalone widths/offsets (outside a grid container) — sized from the
   parent's rendered width, so they track the grid at any viewport. Used by
   halif/heading and halif/text spans; a future tab nav item is .halif-w-3.
   Below 768px elements fall back to natural full-width flow. */
@media (min-width: 768px) {
  .halif-w-1 {
    width: calc(1 * (100% - 11 * var(--grid-gap)) / 12);
  }

  .halif-w-2 {
    width: calc(2 * (100% - 11 * var(--grid-gap)) / 12 + 1 * var(--grid-gap));
  }

  .halif-w-3 {
    width: calc(3 * (100% - 11 * var(--grid-gap)) / 12 + 2 * var(--grid-gap));
  }

  .halif-w-4 {
    width: calc(4 * (100% - 11 * var(--grid-gap)) / 12 + 3 * var(--grid-gap));
  }

  .halif-w-5 {
    width: calc(5 * (100% - 11 * var(--grid-gap)) / 12 + 4 * var(--grid-gap));
  }

  .halif-w-6 {
    width: calc(6 * (100% - 11 * var(--grid-gap)) / 12 + 5 * var(--grid-gap));
  }

  .halif-w-7 {
    width: calc(7 * (100% - 11 * var(--grid-gap)) / 12 + 6 * var(--grid-gap));
  }

  .halif-w-8 {
    width: calc(8 * (100% - 11 * var(--grid-gap)) / 12 + 7 * var(--grid-gap));
  }

  .halif-w-9 {
    width: calc(9 * (100% - 11 * var(--grid-gap)) / 12 + 8 * var(--grid-gap));
  }

  .halif-w-10 {
    width: calc(10 * (100% - 11 * var(--grid-gap)) / 12 + 9 * var(--grid-gap));
  }

  .halif-w-11 {
    width: calc(11 * (100% - 11 * var(--grid-gap)) / 12 + 10 * var(--grid-gap));
  }

  .halif-w-12 {
    width: 100%;
  }

  .halif-offset-1 {
    margin-left: calc(1 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-2 {
    margin-left: calc(2 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-3 {
    margin-left: calc(3 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-4 {
    margin-left: calc(4 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-5 {
    margin-left: calc(5 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-6 {
    margin-left: calc(6 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-7 {
    margin-left: calc(7 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-8 {
    margin-left: calc(8 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-9 {
    margin-left: calc(9 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-10 {
    margin-left: calc(10 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }

  .halif-offset-11 {
    margin-left: calc(11 * ((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  }
}

/* =============================================================
   Grid guide overlay (Figma-style)
   Toggled in the editor by assets/js/grid-guides-editor.js, which adds
   .halif-grid-guides to .editor-styles-wrapper; on the frontend by `?grid`
   on any URL, which puts the same class on <body> (inc/enqueue.php). Column
   stops are computed from the rendered width, so guides align with
   .halif-grid at any canvas size and cover exactly the 1200px container
   when there is room for it.
   ============================================================= */

.halif-grid-guides {
  position: relative;
}

.halif-grid-guides::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(var(--container-max), 100%);
  background: repeating-linear-gradient(to right,
      var(--grid-guide-color) 0,
      var(--grid-guide-color) calc((100% - 11 * var(--grid-gap)) / 12),
      transparent calc((100% - 11 * var(--grid-gap)) / 12),
      transparent calc((100% - 11 * var(--grid-gap)) / 12 + var(--grid-gap)));
  pointer-events: none;
  z-index: 9999;
}

/* =============================================================
   Section spacing — resolved per breakpoint. Blocks only ever use
   the resolved names (--section-pad-top etc.); these overrides swap
   in the tablet/mobile scale.
   ============================================================= */

/* Lead-line offset — resolved per breakpoint, same technique as the spacing
   and typography scales below: blocks only ever use --lead-offset/--lead-gutter. */

@media (max-width: 1023px) {
  :root {
    --lead-offset: calc(3 * var(--grid-part));
  }
}

@media (max-width: 767px) {
  :root {
    --lead-offset: calc(2 * var(--grid-part));
    --lead-gutter: 16px;
    /* a column is only ~12px wide at 375px, so the empty-column gutter
       collapses to the mobile grid gutter and the line keeps a usable length */
  }
}

@media (max-width: 1023px) {
  :root {
    --section-pad-top: var(--section-pad-tablet-top);
    --section-pad-top-md: var(--section-pad-tablet-top-md);
    --section-pad-top-sm: var(--section-pad-tablet-top-sm);
    --section-pad-bottom-xl: var(--section-pad-tablet-bottom-xl);
    --section-pad-bottom: var(--section-pad-tablet-bottom);
    --section-pad-bottom-sm: var(--section-pad-tablet-bottom-sm);
    --columns-vspace: var(--columns-vspace-tablet);
  }
}

@media (max-width: 767px) {
  :root {
    --section-pad-top: var(--section-pad-mobile-top);
    --section-pad-top-md: var(--section-pad-mobile-top-md);
    --section-pad-top-sm: var(--section-pad-mobile-top-sm);
    --section-pad-bottom-xl: var(--section-pad-mobile-bottom-xl);
    --section-pad-bottom: var(--section-pad-mobile-bottom);
    --section-pad-bottom-sm: var(--section-pad-mobile-bottom-sm);
    --columns-vspace: var(--columns-vspace-mobile);
  }
}

/* halif/pricing — mobile (client values are the desktop spec; these are the
   phone step-downs, PROVISIONAL). The cards become a one-card-per-screen
   swipe track below 768px (blocks-src/pricing/style.css), so the block is
   about one screen tall instead of four — the desktop air around it was
   sized for a row that no longer exists here. */
@media (max-width: 767px) {
  :root {
    --pricing-card-peek: 110px;
    /* how much of the NEXT plan card stays on screen (the promo cards leave
       40px) — a price you can half-read is what makes you swipe. Wider than
       first drawn (client, 2026-08-21: the plan card can be narrower still);
       the card keeps the whole switcher's width above it as its ceiling, so
       what it gives up here is what the next price gets. */
    --pricing-cards-overlap: 100px;
    /* how far the CARDS themselves reach up into the section above — the
       overlap is the effect, so on mobile it is the figure that is set and
       the pull is derived from it. Desktop's 380px pull leaves 154px of card
       in the section above; 380 on a phone would just reserve most of a
       screen of empty ground up there. */
    --pricing-pull-top: calc(
      var(--pricing-pad-top) + var(--pricing-switch-h) +
        var(--pricing-switch-space-bottom) + var(--pricing-cards-overlap)
    );
    --pricing-pad-top: 40px;
    --pricing-switch-space-bottom: 48px;
    /* switcher row → cards (desktop 98px) */
  }
}

/* Matchmaker + testimonial card body — tighter inner padding on mobile
   (client, 2026-08-30: 16/24/12). Both blocks share these tokens. */
@media (max-width: 767px) {
  :root {
    --matchmaker-card-pad-top: 16px;
    --matchmaker-card-pad-x: 24px;
    --matchmaker-card-pad-bottom: 12px;
  }
}

/* =============================================================
   Typography — mobile scale (client spec 2026-08-07). Same
   resolved-token technique as section spacing: blocks keep using
   the desktop token names, mobile swaps the values.
   ============================================================= */

@media (max-width: 767px) {
  :root {
    --text-base: 1rem;
    /* 16px paragraph (desktop 20px) */
    --leading-normal: 1.625;
    /* 26px at 16px — the mobile paragraph takes the size AND the leading the
       "Small" variant has on desktop (16/26), so the whole ladder shifts down
       exactly one rung instead of each rung being retuned on its own
       (client, 2026-08-29). Was 1.75 (28px). */
    --text-body-small: 0.875rem;
    /* 14px — halif/text "Small" (desktop 16px) */
    --leading-body-small: 1.5rem;
    /* 24px (desktop 26px) */
    /* "Small" sits closer to the 16px default than a straight −20% would put
       it (client spec 2026-08-09). */
    --text-body-big: 1.25rem;
    /* 20px — halif/text "Big" (desktop 24px). PROVISIONAL: the client
       specified the desktop 24/36 only. Big used to skip mobile entirely,
       which left it at 1.5x the mobile paragraph where desktop is 1.2x —
       the whole paragraph ladder steps down together now. */
    --leading-body-big: 1.875rem;
    /* 30px at 20px — keeps the desktop 1.5 ratio (desktop 36px) */
    --text-body-huge: 1.75rem;
    /* 28px — halif/text "Huge" (desktop 48px). PROVISIONAL, see above.
       Mobile paragraph ladder: 14 / 16 / 20 / 28 — the larger the size, the
       harder it steps (0.875 / 0.8 / 0.83 / 0.58), which is what keeps the
       top of the scale from eating a phone screen. Was 32px until
       2026-08-21; still too heavy next to the 40px H1. */
    --leading-body-huge: 2.25rem;
    /* 36px at 28px (desktop 58px at 48px) — provisional, see above */
    --text-display-h2: 2rem;
    /* 32px — H2 section lead (desktop 64px); client spec 2026-08-30, was 38px then 30px */
    --leading-display-h2: 2.375rem;
    /* 38px (desktop 70px) — keeps the ~1.27 ratio the 38px size carried */
    --text-display-xl: 2.5rem;
    /* 40px — H1 (desktop 64px). Was 48px (client spec 2026-08-09), which does
       not fit the delivered copy: the home H1 glues "začína spojením" with a
       non-breaking space, and that run measures 361px against a 315px column,
       so the headline broke out of the 30px gutter and touched both screen
       edges. 40px brings it to ~301px with room to spare. */
    --leading-display-xl: 2.75rem;
    /* 44px (desktop 70px) */
    --text-display-md: 1.5rem;
    /* 24px — H3 (desktop 42px) */
    --leading-display-md: 2rem;
    /* 32px (desktop 52px) */
    --text-display-sm: 1.5rem;
    /* 24px — heading size "Small" (desktop 32px) */
    --leading-display-sm: 2rem;
    /* 32px. The desktop leading is 70px — the same figure as H1's — so a
       two-line small heading was spending 140px of a phone screen on two
       lines of 32px type, most of it the space between them. */
    --text-step: 1.375rem;
    /* 22px — steps headline (desktop 24px) */
    --leading-step: 1.75rem;
    /* 28px (desktop 32px) */
    --text-step-text: var(--text-base);
    /* 16px/26px — steps body text follows the mobile paragraph (client
       2026-08-21, superseding the 2026-08-10 spec that kept it at the
       desktop 20px/32px) */
    --leading-step-text: var(--leading-normal);

    /* ---- Elements that are not paragraphs but deliberately sit ON the
       paragraph ladder (client, 2026-08-29): a card title set at the 20px
       "Default" size, a meta line at the 16px "Small" one. They were reading
       the desktop figure on a phone while the paragraphs around them stepped
       down, so a card title ended up LARGER than the section's body copy.
       Each one moves one rung: 24→20, 20→16, 16→14, with its leading cut by
       the same amount the ladder cuts (−6 / −4 / −2).

       Deliberately NOT here: --text-body-lg and everything built on it
       (header nav, buttons, breadcrumb, form labels/options, footer meta,
       department pills, pricing mode switch). That 16px is the site's stable
       UI size — chrome, not text — and the client fixed it at 16px on both
       desktop and mobile. ---- */

    /* Event card */
    --text-event-card-title: 1rem;
    /* 16px (desktop 20px) */
    --leading-event-card-title: 1.5rem;
    /* 24px (desktop 28px) */
    --text-event-card-meta: 0.875rem;
    /* 14px (desktop 16px) */
    --leading-event-card-meta: 1.375rem;
    /* 22px (desktop 24px) */

    /* News card */
    --text-news-card-title: 1rem;
    --leading-news-card-title: 1.5rem;
    --text-news-card-excerpt: 0.875rem;
    --leading-news-card-excerpt: 1.375rem;
    --text-news-chip: 0.875rem;

    /* Matchmaker / testimonial card */
    --text-matchmaker-name: 1rem;
    --leading-matchmaker-name: 1.5rem;
    --text-matchmaker-bio: 0.875rem;
    --leading-matchmaker-bio: 1.375rem;

    /* Pricing card */
    --text-pricing-period: 0.875rem;
    --leading-pricing-period: 1.75rem;
    /* 28px (desktop 30px) — the tracked period label */
    --text-pricing-title: 1rem;
    --leading-pricing-title: 1.5rem;
    --text-pricing-desc: 0.875rem;
    --leading-pricing-desc: 1.375rem;
  }
}

/* =============================================================
   Block spacing — mobile scale. The per-block spacing options
   (heading "Small/Middle/Big/Extra large", text "Small/Middle/Big")
   had NO mobile values: a phone was rendering the desktop figures
   verbatim, so a section lead sat 94px above its paragraph and the
   "extra large" step opened a 260px hole in a 375px-wide frame —
   more empty screen than the block that follows it.

   These are ours, not Figma — no mobile frame specifies them. The
   rule used: roughly half the desktop step for the big ones (a
   phone reads a break at far less travel than a 1440 canvas), a
   gentler cut on the small ones, and nothing below 12px, where the
   step stops reading as a deliberate gap at all. The 8px H1/H2/H3
   "small" steps are already tight and stay as they are.
   ============================================================= */

@media (max-width: 767px) {
  :root {
    /* ---- Heading bottom spacing ---- */
    --heading-space-sm: 16px;
    --heading-space-sm-h2: 4px;
    /* the H2 "small" step is 8px desktop (a tight lead-into-its-own-text gap);
       on a phone it tightens to 4px (client spec 2026-08-30) */
    --heading-space-md: 28px;
    --heading-space-md-h2: 36px;
    --heading-space-lg-h3: 20px;
    --heading-space-md-h4: 28px;
    --heading-space-lg: 44px;
    --heading-space-lg-h2: 24px;
    --heading-space-xl: 96px;
    /* still the widest step by a clear margin — it just no longer costs
       a third of the screen */

    /* ---- Text (paragraph) spacing ---- */
    --text-space-sm: 12px;
    --text-space-md: 16px;
    /* was 24px until 2026-08-21 — the default paragraph's gap read too wide
       against the smaller mobile type */
    --text-space-lg: 40px;
    --text-space-large-sm: 24px;
    --text-space-large-md: 24px;
    --text-space-large-lg: 44px;
    --text-space-huge-md: 24px;
    --text-space-top-huge-lg: 44px;

    /* ---- Checks list ---- */
    --list-check-space-bottom: 36px;
    /* the desktop 70px sits under a two-column block; on a phone the list is
       single-column and already long, so the same gap read as a break in the
       section rather than as the end of a list */

    /* ---- Separator ---- */
    --separator-line-short-space: 20px;
    /* The short rule divides two stacked paragraphs, and 50px on each side
       put ~100px between them on a phone — enough that the rule stopped
       reading as *their* divider and floated on its own. 20px (client spec
       2026-08-30, was 28px) keeps a clear break (40px between the paragraphs)
       while the rule stays attached to
       the pair it separates. */
    --separator-line-space: 32px;
    /* Full-width `is-style-line` rule: 48px → 32px on mobile (client spec
       2026-08-30). Its margins still collapse against the neighbouring
       block's own spacing option, so this is the floor, not an addition. */
  }
}

/* =============================================================
   Segment cards — mobile scale. The card's own measurements are
   Figma-screenshot values taken off the 363px-wide desktop card;
   on a phone the card is 289px and the same vertical insets made
   it 900px tall, so a single card no longer fitted a screen and
   the slider lost the "there are three of these" read. The head
   colour band and the 30px side inset stay put; the vertical air
   and the type step down. Ours, not Figma — no mobile frame
   specifies the card, so every value here is PROVISIONAL.
   ============================================================= */

@media (max-width: 767px) {
  :root {
    --card-top-h: 88px;
    --card-head-pad-bottom: 32px;
    --card-rule-space-top: 36px;
    --card-body-pad-bottom: 36px;
    --card-title-gap: 28px;
    /* logo/icon row → title (desktop 38px) */
    --text-card-title: 1.5rem;
    /* 24px — card headline (desktop 32px). The 32px title set on a 289px
       card broke every two-word segment name onto its own line; 24px is
       also where the rest of the mobile ladder puts a headline of this
       rank (--text-display-md). */
    --leading-card-title: 2rem;
    /* 32px (desktop 40px) */
    --text-card-small: 0.875rem;
    /* 14px — the paragraphs after the card's lead text (desktop 16px).
       Follows --text-body-small so the step down from the lead paragraph
       reads the same on a phone as it does on desktop. */
    --leading-card-small: 1.5rem;
    /* 24px (desktop 26px) */
    --text-card-brand: 1.5rem;
    /* 24px — the text lockup that stands in for a missing department logo
       (desktop 34px); at 9% tracking the desktop size overran the card. */
    --leading-card-brand: 2rem;
    /* 32px (desktop 40px) */
  }
}

/* =============================================================
   Header + buttons — resolved per breakpoint. ≤1023px the nav lives
   in the burger sheet (blocks-src/header/style.css) and the bar
   aligns with the page container instead of the 1440 header grid;
   ≤767px the bar and buttons drop to the mobile scale. Mobile values
   are provisional until the Figma mobile frames are measured —
   only the 84px logo is client-specified.
   ============================================================= */

@media (max-width: 1023px) {
  :root {
    --header-height: 100px;
    --logo-width: 120px;
    --header-gutter: var(--container-inset);
  }
}

@media (max-width: 767px) {
  :root {
    /* Section container — fixed 30px side spacing on mobile */
    --gutter: 30px;

    /* The 12-column grid does not survive the desktop 32px gutter on a phone:
       11 gaps alone come to 352px inside a 315px container, so every track
       collapsed to zero and every full-width grid child (.is-span-m-12) ran
       37px past the container — the stat rows on the home page were losing
       their last word off the right edge. 16px puts the 11 gaps at 176px and
       leaves ~11.6px a column, which is the figure the --lead-offset comment
       below already assumes. It also tightens the card slider, which measures
       its slide gap off the same token. */
    --grid-gap: 16px;

    --header-height: 72px;
    --logo-width: 84px;
    /* client-specified mobile logo width */

    /* Buttons — mobile scale, applies to every .halif-btn site-wide */
    --btn-height: 42px;
    --btn-radius: 21px;
    --btn-pad-x-primary: 20.5px;
    --btn-pad-x-secondary: 24.5px;
    --btn-gap: 12px;
    --text-btn: 1rem;
    /* 16px */
    --btn-row-space-top: 12px;
    --btn-row-space-bottom: 12px;
    /* the desktop 64px above a button row is a desktop figure — on a 375px
       screen it read as a break rather than as "this belongs to the text
       above it". The small bottom margin is a floor under the row: it
       collapses into whatever the next block asks for, so it only shows up
       where nothing else was reserving space. PROVISIONAL — no mobile
       frames, like the rest of the 2026-08-21 mobile pass. */
    --btn-row-space-top-after-cols: 40px;
    /* a button row sitting directly under a stacked column grid (the home
       page's "Discover Tahaluf" CTA below the stat columns) needs more air
       above it than the standard 12px, or it crowds the last column's text
       on a phone. Desktop is untouched — the grid leaves room there.
       PROVISIONAL — no mobile frame delivered. */
    --slider-dashes-space-bottom: 12px;
    /* dash bar → pager number: half the desktop gap, so the slider's footer
       row stays a unit on a short screen. PROVISIONAL, as above. */
  }
}

/* =============================================================
   Footer — mobile scale. The three columns stack (span-m-12), so the
   desktop rhythm (110/180/64px verticals, 24px contact lines) is far
   too loose for a 375px frame. Same resolved-token technique as the
   sections above: the footer CSS keeps its token names, mobile swaps
   the values. Provisional until the Figma mobile footer frame is
   measured — no client-specified mobile footer sizes exist yet.
   ============================================================= */

@media (max-width: 767px) {
  :root {
    --footer-pad-top: 72px;
    --footer-pad-bottom: 56px;
    /* client spec: 56px of air under the last row (the credits line, with the
       language switcher wrapped below it) */
    --footer-columns-to-bottom: 56px;
    --footer-rule-space: 20px;
    /* stacked-column rhythm (logo → contact → menu) */
    --footer-stack-gap: 40px;
    --logo-width-footer: 96px;
    /* the icon row is just another item in the stacked column rhythm */
    --footer-socials-space-top: var(--footer-stack-gap);
    --footer-socials-gap: 16px;
    --footer-socials-size: 22px;

    --footer-contact-title-space-top: 0px;
    --footer-contact-title-space-bottom: 14px;
    --footer-contact-gap: 6px;
    --footer-menu-gap: 8px;

    --text-footer-contact: 1.25rem;
    /* 20px (desktop 24px) */
    --text-footer-meta: 1rem;
    /* 16px — contact label + legal menu (desktop 20px) */
    --leading-footer: 1.75rem;
    /* 28px (desktop 32px) */
  }
}

/* =============================================================
   Form fields — mobile scale (client spec 2026-08-10). The 34px
   inner inset of a 375px-wide input eats a fifth of the line, so
   the whole field family tightens: same resolved-token technique
   as the sections above, the form CSS keeps its token names.
   ============================================================= */

@media (max-width: 767px) {
  :root {
    /* Newsletter — provisional, no mobile frame yet. A 144px chip inside a
       ~315px pill leaves too little of the line for the address to be read,
       so on phones the button hugs its label instead of holding a fixed
       width, and the gap in front of it tightens to the small step. Revisit
       when a mobile sign-up row is designed. */
    --newsletter-btn-w: auto;
    --newsletter-btn-pad-x: var(--btn-pad-x-primary);
    --newsletter-input-gap: var(--space-xs);

    /* text inputs, textareas and the closed select all share this inset */
    --form-input-pad-x: 24px;
    /* the textarea's vertical inset shrinks with it, and the character
       counter — which sits on both insets — moves in with it */
    --form-textarea-pad-y: 0.75rem;
    /* 12px (desktop 16px) */

    /* Dropdown panel. Its rows must keep landing on the SAME text inset as
       the closed control they drop out of, so these two always add up to
       --form-input-pad-x: 2 + 22 = 24, as 8 + 26 = 34 does on desktop. */
    --form-select-menu-pad: 2px;
    --form-select-option-pad-x: 22px;

    /* Checkbox / radio boxes. The markers keep their desktop proportion
       inside the smaller square rather than growing to fill it. The
       dropdown's own tick (--form-tick-size) shrinks with the panel too. */
    --form-control-size: 20px;
    --form-dot-size: 10px;
    --form-check-tick-size: 12px;
    --form-tick-size: 17px;

    /* Switch on the same 28/35 mobile scale as the box beside it. */
    --form-switch-h: 26px;
    --form-switch-w: 46px;
    --form-switch-pad: 3px;

    /* Below 48em the indicator is markers only (the names are dropped — see
       blocks-src/form/style.css), so a 32px row of dots needs less air under
       it than the named row on desktop: 64px total, not 96px. */
    --form-stepper-gap: 32px;
  }
}

/* =============================================================
   Steps slider — grid span per breakpoint (client spec 2026-08-10).
   Every view uses the same construction as desktop: a step occupies
   N grid parts, the last R of them are its right spacing, so the
   text spans (N - R) columns and the stride is N parts — which puts
   the following step one grid gap past the container edge, peeking
   into the bleed area.
     desktop  4 parts, 1 spacing  (3 visible = 12 parts)
     tablet   6 parts, 2 spacing  (2 visible)
     mobile  12 parts, 2 spacing  (1 visible)
   ============================================================= */

@media (max-width: 1023px) {
  :root {
    --steps-visible: 2;
    --steps-gap: calc(2 * var(--grid-part));
    --step-width: calc((100vw - 2 * var(--container-inset)) / 2 - var(--steps-gap));
    /* same exception as mobile below: the stride is half the container, so
       the third step starts exactly on the container edge and peeks through
       the bleed instead of hiding 32px into it. The step keeps its 2-part
       right spacing; only the grid gap that would sit after it is dropped. */
  }
}

@media (max-width: 767px) {
  :root {
    --steps-visible: 1;
    --steps-space-top: 92px;
    --steps-nav-space: 64px;
    --steps-gap: calc(2 * var(--grid-part));
    --step-width: calc(100vw - 2 * var(--container-inset) - var(--steps-gap));
    /* the one exception to the construction above: the step fills the
       container minus its 2-part right spacing, and the stride is the
       container width — so the next step starts exactly on the container
       edge and peeks through the bleed. Adding the grid gap on top (the
       strict reading) would push it a whole 32px past the viewport, since
       here the bleed is only the ~20px gutter and a grid column is
       narrower than the gap itself. */
  }
}