{"id":21,"date":"2026-09-04T09:04:04","date_gmt":"2026-09-04T09:04:04","guid":{"rendered":"https:\/\/preview.deltatheme.com\/kiln\/contact\/"},"modified":"2026-10-21T15:17:06","modified_gmt":"2026-10-21T15:17:06","slug":"contact","status":"publish","type":"page","link":"https:\/\/preview.deltatheme.com\/kiln\/contact\/","title":{"rendered":"Contact"},"content":{"rendered":"\n  <section class=\"section\">\n    <header class=\"sechead\" data-delta-component-opt-out=\"section-head\">\n      <p class=\"sechead__eyebrow eyebrow\">Contact<\/p>\n      <h1 class=\"sechead__title\">Write to us.<\/h1>\n      <p class=\"sechead__lead\">For anything that is not a scoping call: research, disclosure, press, or a question you want answered before you speak to anyone. If you already know you want an engagement, <a href=\"https:\/\/preview.deltatheme.com\/kiln\/book-a-call\/\">book a call<\/a> instead.<\/p>\n    <\/header>\n\n    <figure class=\"pagefig\">\n      <img src=\"https:\/\/preview.deltatheme.com\/kiln\/wp-content\/uploads\/sites\/2\/2026\/09\/kiln-c-team-office.jpg\" alt=\"Collage of three figures at desks in headsets working an incident\" width=\"1200\" height=\"800\">\n    <\/figure>\n  <\/section>\n\n  <section class=\"contact\">\n    <div class=\"contact__copy\">\n      <p class=\"eyebrow\">Direct<\/p>\n      <h2 class=\"contact__title\">The short version<\/h2>\n\n      <dl class=\"deflist\">\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Email<\/dt>\n          <dd class=\"deflist__v\"><a href=\"mailto:hello@kiln.example\">hello@kiln.example<\/a><\/dd>\n        <\/div>\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Disclosure<\/dt>\n          <dd class=\"deflist__v\"><a href=\"mailto:security@kiln.example\">security@kiln.example<\/a><br><span class=\"deflist__note\">PGP key on request. We answer disclosure mail first.<\/span><\/dd>\n        <\/div>\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Where<\/dt>\n          <dd class=\"deflist__v\">Tallinn, and remote across Europe<\/dd>\n        <\/div>\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Reply<\/dt>\n          <dd class=\"deflist__v\">One working day. Retainer clients, fifteen minutes.<\/dd>\n        <\/div>\n      <\/dl>\n\n      <ul class=\"badges\">\n        <li class=\"badge\" data-delta-component=\"badge\">NDA on request<\/li>\n        <li class=\"badge\" data-delta-component=\"badge\">PGP<\/li>\n        <li class=\"badge\" data-delta-component=\"badge\">No sales team<\/li>\n      <\/ul>\n    <\/div>\n\n    <div class=\"contact__form\">\n      <div class=\"intake\" data-delta-component-opt-out=\"intake-form\">\n        <p class=\"prompt\"><span class=\"prompt__host\">kiln@contact:~$<\/span> new-message<\/p>\n        <form class=\"form\" novalidate>\n          <div class=\"field\">\n            <label class=\"field__lbl\" for=\"c-name\">Name <span class=\"field__req\">*<\/span><\/label>\n            <input class=\"field__in\" id=\"c-name\" name=\"name\" type=\"text\" required autocomplete=\"name\">\n          <\/div>\n          <div class=\"field\">\n            <label class=\"field__lbl\" for=\"c-email\">Email <span class=\"field__req\">*<\/span><\/label>\n            <input class=\"field__in\" id=\"c-email\" name=\"email\" type=\"email\" required autocomplete=\"email\">\n          <\/div>\n          <div class=\"field field--wide\">\n            <label class=\"field__lbl\" for=\"c-subject\">Subject<\/label>\n            <select class=\"field__in\" id=\"c-subject\" name=\"subject\">\n              <option>General question<\/option>\n              <option>Vulnerability disclosure<\/option>\n              <option>Research or press<\/option>\n              <option>Working with us<\/option>\n              <option>Something else<\/option>\n            <\/select>\n          <\/div>\n          <div class=\"field field--wide\">\n            <label class=\"field__lbl\" for=\"c-msg\">Message <span class=\"field__req\">*<\/span><\/label>\n            <textarea class=\"field__in field__in--area\" id=\"c-msg\" name=\"message\" rows=\"6\" required><\/textarea>\n            <p class=\"field__hint\">Do not put anything sensitive in here. If it is sensitive, mail the disclosure address and we will send you a key.<\/p>\n          <\/div>\n          <button class=\"btn btn--primary form__send\" type=\"submit\">Send<\/button>\n          <p class=\"form__msg\" role=\"status\"><\/p>\n          <p class=\"form__fine\">Encrypted in transit. We keep contact mail for ninety days, then delete it.<\/p>\n        <\/form>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"section\">\n    <header class=\"sechead\" data-delta-component=\"section-head\">\n      <p class=\"sechead__eyebrow eyebrow\">Where<\/p>\n      <h2 class=\"sechead__title\">Tallinn, and remote.<\/h2>\n      <p class=\"sechead__lead\">The office is in Tallinn and it is where the hardware lives. Everyone works across European time, and most engagements never need us in the room \u2014 when one does, we travel.<\/p>\n    <\/header>\n\n    <div class=\"embed\">\n      <div class=\"embed__slot\">\n        <iframe src=\"https:\/\/www.google.com\/maps?q=Tallinn%2C%20Estonia&amp;output=embed\" title=\"Map showing Tallinn, Estonia\" loading=\"lazy\" referrerpolicy=\"no-referrer-when-downgrade\"><\/iframe>\n      <\/div>\n    <\/div>\n  <\/section>\n","protected":false},"excerpt":{"rendered":"<p>Contact Write to us. For anything that is not a scoping call: research, disclosure, press, or a question you want answered before you speak to anyone. If you already know you want an engagement, book a call instead. Direct The short version Email hello@kiln.example Disclosure security@kiln.example PGP key on request. We answer disclosure mail first. Where Tallinn, and remote across Europe Reply One working day. Retainer clients, fifteen minutes. NDA on request PGP No sales team kiln@contact:~$<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-21","page","type-page","status-publish","hentry"],"delta":{"html":"\n  <section class=\"section\">\n    <header class=\"sechead\" data-delta-component-opt-out=\"section-head\">\n      <p class=\"sechead__eyebrow eyebrow\">Contact<\/p>\n      <h1 class=\"sechead__title\">Write to us.<\/h1>\n      <p class=\"sechead__lead\">For anything that is not a scoping call: research, disclosure, press, or a question you want answered before you speak to anyone. If you already know you want an engagement, <a href=\"https:\/\/preview.deltatheme.com\/kiln\/book-a-call\/\">book a call<\/a> instead.<\/p>\n    <\/header>\n\n    <figure class=\"pagefig\">\n      <img src=\"https:\/\/preview.deltatheme.com\/kiln\/wp-content\/uploads\/sites\/2\/2026\/09\/kiln-c-team-office.jpg\" alt=\"Collage of three figures at desks in headsets working an incident\" width=\"1200\" height=\"800\">\n    <\/figure>\n  <\/section>\n\n  <section class=\"contact\">\n    <div class=\"contact__copy\">\n      <p class=\"eyebrow\">Direct<\/p>\n      <h2 class=\"contact__title\">The short version<\/h2>\n\n      <dl class=\"deflist\">\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Email<\/dt>\n          <dd class=\"deflist__v\"><a href=\"mailto:hello@kiln.example\">hello@kiln.example<\/a><\/dd>\n        <\/div>\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Disclosure<\/dt>\n          <dd class=\"deflist__v\"><a href=\"mailto:security@kiln.example\">security@kiln.example<\/a><br><span class=\"deflist__note\">PGP key on request. We answer disclosure mail first.<\/span><\/dd>\n        <\/div>\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Where<\/dt>\n          <dd class=\"deflist__v\">Tallinn, and remote across Europe<\/dd>\n        <\/div>\n        <div class=\"deflist__row\">\n          <dt class=\"deflist__k\">Reply<\/dt>\n          <dd class=\"deflist__v\">One working day. Retainer clients, fifteen minutes.<\/dd>\n        <\/div>\n      <\/dl>\n\n      <ul class=\"badges\">\n        <li class=\"badge\" data-delta-component=\"badge\">NDA on request<\/li>\n        <li class=\"badge\" data-delta-component=\"badge\">PGP<\/li>\n        <li class=\"badge\" data-delta-component=\"badge\">No sales team<\/li>\n      <\/ul>\n    <\/div>\n\n    <div class=\"contact__form\">\n      <div class=\"intake\" data-delta-component-opt-out=\"intake-form\">\n        <p class=\"prompt\"><span class=\"prompt__host\">kiln@contact:~$<\/span> new-message<\/p>\n        <form class=\"form\" novalidate>\n          <div class=\"field\">\n            <label class=\"field__lbl\" for=\"c-name\">Name <span class=\"field__req\">*<\/span><\/label>\n            <input class=\"field__in\" id=\"c-name\" name=\"name\" type=\"text\" required autocomplete=\"name\">\n          <\/div>\n          <div class=\"field\">\n            <label class=\"field__lbl\" for=\"c-email\">Email <span class=\"field__req\">*<\/span><\/label>\n            <input class=\"field__in\" id=\"c-email\" name=\"email\" type=\"email\" required autocomplete=\"email\">\n          <\/div>\n          <div class=\"field field--wide\">\n            <label class=\"field__lbl\" for=\"c-subject\">Subject<\/label>\n            <select class=\"field__in\" id=\"c-subject\" name=\"subject\">\n              <option>General question<\/option>\n              <option>Vulnerability disclosure<\/option>\n              <option>Research or press<\/option>\n              <option>Working with us<\/option>\n              <option>Something else<\/option>\n            <\/select>\n          <\/div>\n          <div class=\"field field--wide\">\n            <label class=\"field__lbl\" for=\"c-msg\">Message <span class=\"field__req\">*<\/span><\/label>\n            <textarea class=\"field__in field__in--area\" id=\"c-msg\" name=\"message\" rows=\"6\" required><\/textarea>\n            <p class=\"field__hint\">Do not put anything sensitive in here. If it is sensitive, mail the disclosure address and we will send you a key.<\/p>\n          <\/div>\n          <button class=\"btn btn--primary form__send\" type=\"submit\">Send<\/button>\n          <p class=\"form__msg\" role=\"status\"><\/p>\n          <p class=\"form__fine\">Encrypted in transit. We keep contact mail for ninety days, then delete it.<\/p>\n        <\/form>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"section\">\n    <header class=\"sechead\" data-delta-component=\"section-head\">\n      <p class=\"sechead__eyebrow eyebrow\">Where<\/p>\n      <h2 class=\"sechead__title\">Tallinn, and remote.<\/h2>\n      <p class=\"sechead__lead\">The office is in Tallinn and it is where the hardware lives. Everyone works across European time, and most engagements never need us in the room \u2014 when one does, we travel.<\/p>\n    <\/header>\n\n    <div class=\"embed\">\n      <div class=\"embed__slot\">\n        <iframe src=\"https:\/\/www.google.com\/maps?q=Tallinn%2C%20Estonia&amp;output=embed\" title=\"Map showing Tallinn, Estonia\" loading=\"lazy\" referrerpolicy=\"no-referrer-when-downgrade\"><\/iframe>\n      <\/div>\n    <\/div>\n  <\/section>\n","css":"\/* Contact \u2014 page-scoped. The two-column band matches the service bands and the\n   booking band: copy in one column, the form in the other, one rule between. *\/\n.contact {\n  display: grid;\n  border-bottom: var(--rule);\n}\n\n.contact__copy {\n  padding: var(--space-3xl) var(--pad);\n}\n\n.contact__title {\n  margin: 0 0 var(--space-lg);\n  font-family: var(--font-title);\n  font-size: var(--title-md-size);\n  line-height: var(--title-md-leading);\n  letter-spacing: var(--title-md-tracking);\n  font-weight: var(--weight-bold);\n}\n\n\/* The form column sits one step off the page ground, the same as the intake\n   column on the home page. The controls keep --color-surface-body, so the\n   fields read as cut into the panel rather than floating on it. *\/\n.contact__form {\n  padding: var(--space-3xl) var(--pad);\n  background: var(--color-surface-subtle);\n}\n\n\/* Ruled definition list. One row per fact, the key in mono on the left from sm\n   up and above the value below it, so the column never crushes the value. *\/\n.deflist {\n  margin: 0 0 var(--space-xl);\n  border-top: var(--rule);\n}\n\n.deflist__row {\n  display: grid;\n  gap: var(--space-2xs);\n  padding-block: var(--space-md);\n  border-bottom: var(--rule);\n}\n\n.deflist__k {\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n  letter-spacing: var(--tracking-wide);\n  text-transform: uppercase;\n  color: var(--color-ink-muted);\n}\n\n.deflist__v {\n  margin: 0;\n  color: var(--color-ink);\n}\n\n\/* :not([class]) guard \u2014 a bare `.x a { color }` is 0,1,1 and outranks a\n   component's own colour, which paints button labels the wrong value. *\/\n.deflist__v a:not([class]) {\n  color: var(--color-action);\n}\n\n.deflist__note {\n  display: block;\n  margin-top: var(--space-2xs);\n  font-size: var(--text-sm-size);\n  line-height: var(--text-sm-leading);\n  color: var(--color-ink-muted);\n}\n\n\/* Map embed. The frame is a third party's, so the wrapper owns the ratio and\n   the hairline and the iframe simply fills it \u2014 the height is reserved before\n   the frame loads and the page does not jump. Shorter ratio on a narrow screen,\n   where a wide band shows a street and no context. *\/\n.embed {\n  padding: 0 var(--pad) var(--space-3xl);\n}\n\n.embed__slot {\n  aspect-ratio: 4 \/ 3;\n  background: var(--color-surface-subtle);\n  border: var(--rule);\n}\n\n.embed__slot > iframe {\n  display: block;\n  inline-size: 100%;\n  block-size: 100%;\n  border: 0;\n}\n\n@media (min-width: 40rem) {\n  .embed__slot {\n    aspect-ratio: 21 \/ 9;\n  }\n}\n\n@media (min-width: 40rem) {\n  .deflist__row {\n    grid-template-columns: 10rem 1fr;\n    gap: var(--space-lg);\n    align-items: baseline;\n  }\n}\n\n@media (min-width: 64rem) {\n  .contact {\n    grid-template-columns: 1fr 1fr;\n    align-items: start;\n  }\n\n  .contact__form {\n    border-left: var(--rule);\n  }\n}","js":"","styles":[{"handle":"21press-delta-tokens","url":"https:\/\/preview.deltatheme.com\/kiln\/wp-content\/uploads\/sites\/2\/21press-delta\/site\/tokens.css","inline":""},{"handle":"21press-delta-engine","url":"https:\/\/preview.deltatheme.com\/kiln\/wp-content\/themes\/delta\/assets\/frontend\/css\/base.css","inline":""},{"handle":"21press-delta-components","url":"https:\/\/preview.deltatheme.com\/kiln\/wp-content\/uploads\/sites\/2\/21press-delta\/site\/components.css","inline":"\/**\n * Site CSS \u2014 element defaults, composed properties, surface rows, context classes.\n * Delta's floor (reset, page frame, nav reset) lives in the theme's base.css.\n * Agent-authored via set-site-assets. Prefer var(--\u2026) from tokens.css.\n *\n * Colour works in rows. tokens.css holds the light row on :root. This file\n * holds the dark row and the contrast row, the same job names with other\n * values. A section switches rows with one class (surface-contrast); the\n * whole site switches with data-theme=\"dark\" on <html>. Nothing inside a\n * section changes: every element reads the same names.\n *\/\n\n:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {\n  outline: 2px solid var(--color-focus, var(--color-action));\n  outline-offset: 2px;\n}\n\nul.delta-nav ul {\n  padding-left: var(--space-md);\n}\n\nbody {\n  font-family: var(--font-text);\n  font-size: var(--text-md-size);\n  line-height: var(--text-md-leading);\n  letter-spacing: var(--text-md-tracking);\n}\n\nh1,\nh2,\nh3,\nh4 {\n  font-family: var(--font-title);\n  color: var(--color-ink);\n}\n\nh1 {\n  font-size: var(--title-xl-size);\n  line-height: var(--title-xl-leading);\n  letter-spacing: var(--title-xl-tracking);\n  font-weight: var(--weight-semibold);\n}\n\nh2 {\n  font-size: var(--title-lg-size);\n  line-height: var(--title-lg-leading);\n  letter-spacing: var(--title-lg-tracking);\n  font-weight: var(--weight-semibold);\n}\n\nh3 {\n  font-size: var(--title-md-size);\n  line-height: var(--title-md-leading);\n  letter-spacing: var(--title-md-tracking);\n  font-weight: var(--weight-semibold);\n}\n\ncode,\nkbd,\nsamp {\n  font-family: var(--font-mono);\n  font-size: var(--text-code-size);\n  line-height: var(--text-code-leading);\n}\n\npre {\n  font-family: var(--font-mono);\n  font-size: var(--text-code-size);\n  line-height: var(--text-code-leading);\n  overflow-x: auto;\n}\n\n\/* The block already took the code size; code inside it must not shrink again. *\/\npre code {\n  font-size: inherit;\n  line-height: inherit;\n}\n\n\/* Eyebrow: a kicker above a heading, set in the label step. Not a heading. *\/\n.eyebrow {\n  font-size: var(--text-label-size);\n  line-height: var(--text-label-leading);\n  letter-spacing: var(--text-label-tracking);\n  text-transform: uppercase;\n  font-weight: var(--weight-semibold);\n  color: var(--color-ink-muted);\n}\n\n\/**\n * Content rhythm. The floor zeroes browser margins; this puts space above each\n * text block, between siblings only, so the first and last never leave a gap.\n * Zero specificity (:where), so any template or recipe rule wins.\n *\/\n:where(p, ul, ol, dl, pre, blockquote, figure, table) + :where(p, ul, ol, dl, pre, blockquote, figure, table) {\n  margin-block-start: var(--space-sm);\n}\n\n:where(p) + :where(p) {\n  margin-block-start: var(--space-md);\n}\n\n:where(h1, h2, h3, h4, h5, h6) + :where(p, ul, ol, dl, pre, blockquote, figure, table) {\n  margin-block-start: var(--space-sm);\n}\n\n\/* A page title wants one step more under it than a heading in the flow. *\/\n:where(h1) + :where(p, ul, ol, dl, pre, blockquote, figure, table) {\n  margin-block-start: var(--space-md);\n}\n\n:where(p, ul, ol, dl, pre, blockquote, figure, table) + :where(h1, h2, h3, h4, h5, h6) {\n  margin-block-start: var(--space-lg);\n}\n\n:where(.eyebrow) + :where(h1, h2, h3, h4, h5, h6) {\n  margin-block-start: var(--space-xs);\n}\n\n\/* Unclassed text links only. A bare `a` \/ `a:hover` colour rule is 0,1,1 on\n   hover and paints `.btn` labels the same colour as the fill. *\/\na:not([class]) {\n  color: var(--color-ink);\n}\n\na:not([class]):hover {\n  color: var(--color-ink-muted);\n}\n\n.section__inner {\n  \/* Running text. A shorter line: calc(var(--layout-content) * 0.7) \u2014 never a raw ch. *\/\n  max-width: var(--layout-content);\n  font-size: var(--text-md-size);\n  line-height: var(--text-md-leading);\n  letter-spacing: var(--text-md-tracking);\n  color: var(--color-ink);\n}\n\n.section__inner h2,\n.section__inner h3 {\n  font-family: var(--font-title);\n  font-weight: var(--weight-medium);\n}\n\n.section__inner h2 {\n  font-size: var(--title-lg-size);\n  line-height: var(--title-lg-leading);\n  letter-spacing: var(--title-lg-tracking);\n}\n\n.section__inner h3 {\n  font-size: var(--title-md-size);\n  line-height: var(--title-md-leading);\n  letter-spacing: var(--title-md-tracking);\n}\n\n.section__inner p {\n  color: var(--color-ink-muted);\n}\n\n\/* Links inside body text only. Never a bare `.x a { color }` (0,1,1): it outranks\n   a component's own color (.btn is 0,1,0) and paints button labels invisible.\n   The link_color_scope write invariant enforces this; the seed obeys it too.\n   Hover must be restated: this selector ties a:not([class]):hover at 0,2,1. *\/\n.section__inner a:not([class]) {\n  color: var(--color-ink);\n}\n\n.section__inner a:not([class]):hover {\n  color: var(--color-ink-muted);\n}\n\n\/**\n * Surface rows.\n *\n * The light row lives in tokens.css (:root). The two rows below set the same\n * job names with other values. A component never knows which row it is in.\n *\/\n\n\/* Site-wide dark mode: data-theme=\"dark\" on <html>. Inert until something\n   sets it (the light-and-dark recipe adds a header script and a toggle).\n   Declared on :root, never on body: a value on body would override the\n   dark value body inherits from <html>. *\/\n:root[data-theme=\"dark\"] {\n  --color-surface-body: #18181B;\n  --color-surface-subtle: #1F1F22;\n  --color-surface-raised: #27272A;\n  --color-ink: #FAFAFA;\n  --color-ink-muted: #A1A1AA;\n  --color-border: #3F3F46;\n  --color-action: #FAFAFA;\n  --color-action-hover: #E4E4E7;\n  --color-action-subtle: #27272A;\n  --color-focus: #FAFAFA;\n  --color-on-action: #18181B;\n  --color-danger: #F87171;\n  --color-danger-bg: #452A2C;\n  --color-success: #4ADE80;\n  --color-success-bg: #224030;\n  --color-warning: #FBBF24;\n  --color-warning-bg: #45391D;\n  \/* Shadows need their own dark values: a light shadow on a dark ground is invisible. *\/\n  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 \/ 0.4);\n  --shadow-md: 0 4px 6px -1px rgb(0 0 0 \/ 0.5), 0 2px 4px -2px rgb(0 0 0 \/ 0.5);\n  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 \/ 0.6), 0 4px 6px -4px rgb(0 0 0 \/ 0.6);\n}\n\n\/* The inverted band: dark on a light page, one per page. Same values as the\n   dark row. Put the class (or the attribute) on the section wrapper and\n   nothing inside it needs to change. *\/\n.surface-contrast,\n[data-surface=\"contrast\"] {\n  --color-surface-body: #18181B;\n  --color-surface-subtle: #1F1F22;\n  --color-surface-raised: #27272A;\n  --color-ink: #FAFAFA;\n  --color-ink-muted: #A1A1AA;\n  --color-border: #3F3F46;\n  --color-action: #FAFAFA;\n  --color-action-hover: #E4E4E7;\n  --color-action-subtle: #27272A;\n  --color-focus: #FAFAFA;\n  --color-on-action: #18181B;\n  --color-danger: #F87171;\n  --color-danger-bg: #452A2C;\n  --color-success: #4ADE80;\n  --color-success-bg: #224030;\n  --color-warning: #FBBF24;\n  --color-warning-bg: #45391D;\n  \/* Shadows need their own dark values: a light shadow on a dark ground is invisible. *\/\n  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 \/ 0.4);\n  --shadow-md: 0 4px 6px -1px rgb(0 0 0 \/ 0.5), 0 2px 4px -2px rgb(0 0 0 \/ 0.5);\n  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 \/ 0.6), 0 4px 6px -4px rgb(0 0 0 \/ 0.6);\n}\n\n\/* The inverted band on a dark page is light: the light row again. *\/\n:root[data-theme=\"dark\"] .surface-contrast,\n:root[data-theme=\"dark\"] [data-surface=\"contrast\"] {\n  --color-surface-body: #FFFFFF;\n  --color-surface-subtle: #F4F4F5;\n  --color-surface-raised: #FFFFFF;\n  --color-ink: #09090B;\n  --color-ink-muted: #6E6E77;\n  --color-border: #E4E4E7;\n  --color-action: #18181B;\n  --color-action-hover: #27272A;\n  --color-action-subtle: #F4F4F5;\n  --color-focus: #18181B;\n  --color-on-action: #FAFAFA;\n  --color-danger: #DC2626;\n  --color-danger-bg: #FEF2F2;\n  --color-success: #16A34A;\n  --color-success-bg: #F0FDF4;\n  --color-warning: #D97706;\n  --color-warning-bg: #FFFBEB;\n  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 \/ 0.05);\n  --shadow-md: 0 4px 6px -1px rgb(0 0 0 \/ 0.10), 0 2px 4px -2px rgb(0 0 0 \/ 0.10);\n  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 \/ 0.10), 0 4px 6px -4px rgb(0 0 0 \/ 0.10);\n}\n\n\/* Every surface paints its own row. `color` must be set here: it inherits as\n   an already computed value, so a rebinding alone would leave the old ink. *\/\nbody,\n.surface-contrast,\n[data-surface=\"contrast\"] {\n  background: var(--color-surface-body);\n  color: var(--color-ink);\n}\n\n\/* Quiet band between sections. Same row, one step off the page. *\/\n.surface-subtle {\n  background: var(--color-surface-subtle);\n}\n\n\/* A lifted card or panel. On light the border and shadow lift it; on dark\n   the tone does. The agent writes the class and never chooses between them. *\/\n.surface-raised {\n  background: var(--color-surface-raised);\n  border: var(--border-width) solid var(--color-border);\n  box-shadow: var(--shadow-sm);\n}\n\n\/* The contrast band in this site's own colours, carried over from the names the earlier seed gave them. *\/\n.surface-contrast,\n[data-surface=\"contrast\"] {\n  --color-surface-body: var(--color-surface-contrast);\n  --color-on-action: var(--color-surface-contrast);\n  --color-ink: var(--color-ink-on-contrast);\n  --color-action: var(--color-ink-on-contrast);\n  --color-focus: var(--color-ink-on-contrast);\n  --color-ink-muted: var(--color-ink-muted-on-contrast);\n  --color-action-hover: var(--color-ink-muted-on-contrast);\n  --color-border: var(--color-border-on-contrast);\n}\n\n\/**\n * Kept from this site at the seed upgrade: its own rules, its changes to seed\n * rules, and rules of the earlier seed that this seed has no version of.\n * They come after the seed's rules, so where both speak these win.\n *\/\n\n\/**\n * Site CSS \u2014 element defaults, composed properties, context classes.\n *\/\n\n\/* ---- Composed properties -------------------------------------------\n   Site-level decisions the token file does not carry. Bare names: the\n   --color-* \/ --space-* namespace belongs to tokens.json. *\/\n\/* Declared on every element, not on :root. A custom property that references\n   another is resolved on the element that declares it, and descendants inherit\n   the finished value. On :root these two froze to the light colours, so\n   .inverted and dark mode, which rebind --color-border and --color-ink, could\n   not reach them. On * each element resolves them from its own colour tokens. *\/\n* {\n  --rule: var(--border-width) solid var(--color-border);\n  \/* A control's edge is not a layout hairline. --color-border is 1.19:1 on the\n     page ground \u2014 fine for a rule that separates blocks, and a failure on\n     anything a person operates, where WCAG 1.4.11 asks for 3:1. Form controls\n     take this token; the secondary and ghost buttons take --color-ink-muted,\n     which clears the same floor without a token of its own.\n     Named here so the intent is on the record and the two can move apart. *\/\n  --color-field-border: var(--color-ink);\n}\n\n:root {\n  --pad: var(--layout-section-inline);\n  --mono-sm: var(--text-xs-size);\n  \/* Vertical rhythm. Named for the job, not the size \u2014 --gap-md would only be a\n     second word for --space-md and would not tell anyone where to use it.\n     These five say where they belong, so a block picks the one that matches its\n     relationship and the size follows. Change the mapping here and the rhythm\n     moves everywhere at once, which is the point of naming them at all.\n\n     Vertical space is set with `gap` on the parent, not margin on the child.\n     Where a block needs two rhythms \u2014 a label hugging its heading inside a\n     looser stack \u2014 nest a container rather than reaching back for margins.\n     Two exceptions that gap cannot express: `margin-top: auto` pinning a link\n     to the bottom of a card, and the space below the last child of a block,\n     which is that block's padding. *\/\n  --gap-tight: var(--space-2xs);   \/* a label and the thing it labels *\/\n  --gap-stack: var(--space-md);    \/* siblings inside one text block *\/\n  --gap-inline: var(--space-sm);   \/* items sitting in a row *\/\n  --gap-block: var(--space-lg);    \/* distinct blocks inside a component *\/\n  --gap-group: var(--space-2xl);   \/* major groups inside a section *\/\n\n  \/* Line length. Every max-width on running text derives from --layout-content,\n     so the whole family moves when that one token moves. There is no bare ch\n     value left on the site: the twelve that outlived the first pass now sit on\n     these six steps, each within a character or two of what it replaced.\n     --line-length-title caps a section h2; --line-length-title-page caps the h1\n     in a section head, which is set one size up and needs the wider cap.\n     Resolved values at the current 65ch content measure are in the comments. *\/\n  --line-length-title: calc(var(--layout-content) * 0.28);       \/* ~18ch \u2014 section titles *\/\n  --line-length-title-page: calc(var(--layout-content) * 0.37);  \/* ~24ch \u2014 page titles *\/\n  --line-length-xs: calc(var(--layout-content) * 0.5);           \/* ~33ch \u2014 cell captions *\/\n  --line-length-sm: calc(var(--layout-content) * 0.65);          \/* ~42ch \u2014 leads, cells *\/\n  --line-length-md: calc(var(--layout-content) * 0.71);          \/* ~46ch \u2014 body in a column *\/\n  --line-length-lg: calc(var(--layout-content) * 1.05);          \/* ~68ch \u2014 long-form *\/\n\n  \/* Breakpoints are literals by necessity: a custom property cannot be read in\n     a media query condition. Every query on this site is written against the\n     token values \u2014 40rem is --breakpoint-sm, 64rem is --breakpoint-md, and\n     63.99rem is the max-width side of md. Change a breakpoint token and these\n     literals must be changed with it. --breakpoint-lg (80rem) is unused: no\n     layout on the site changes at that width. *\/\n}\n\n\/* ---- Element defaults ------------------------------------------------ *\/\n\n\/* border-box for everything. The site was written without it, so every box was\n   content-box: .site-header and .site-footer both set inline-size:100% and then\n   add padding and a side rule on top, which put them 2x--pad wider than .shell\n   at every width and overflowed the viewport below ~1498px. .field__in did the\n   same inside its column. The templates already say they are \"contained to the\n   same measure as .shell\" \u2014 this is what makes that true. *\/\n*,\n*::before,\n*::after {\n  box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n  font-family: var(--font-text);\n  font-size: var(--text-md-size);\n  line-height: var(--text-md-leading);\n  letter-spacing: var(--text-md-tracking);\n  color: var(--color-ink);\n  background: var(--color-surface-body);\n  -webkit-font-smoothing: antialiased;\n}\n\na {\n  color: var(--color-action);\n}\n\n\/* :where() keeps this at 0,0,1. A bare a:hover is 0,1,1 and outranks a\n   component's own color (.btn--primary is 0,1,0) \u2014 which paints a button label\n   in the same value the hover state paints its background. *\/\na:where(:hover) {\n  color: var(--color-action-hover);\n}\n\n:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {\n  outline: var(--space-3xs) solid var(--color-focus);\n  outline-offset: var(--space-3xs);\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n}\n\nhr {\n  border: 0;\n  border-top: var(--rule);\n  margin: var(--space-2xl) 0;\n}\n\nimg {\n  max-width: 100%;\n  height: auto;\n}\n\n\/* ---- Layout context -------------------------------------------------\n   Full-bleed section, constrained inner column. Every page inherits this\n   skeleton, so two pages built months apart still reconcile.\n\n   The page column is the theme's own main.delta-main, not a wrapper div in\n   each page. Every page and template used to open with <div class=\"shell\">,\n   which made the whole page one block: the Front panel lists the direct\n   children of the page as its Sections, so it showed one entry and could\n   reorder nothing. Pages and templates now start with their sections.\n   inline-size is needed because .delta-site is a flex column: with\n   margin-inline:auto and no width, the column shrinks to its content and the\n   widest child pushes it past the viewport. *\/\n.delta-main {\n  inline-size: 100%;\n  max-width: var(--layout-max);\n  margin-inline: auto;\n  background: var(--color-surface-body);\n  border-inline: var(--rule);\n}\n\n.delta-main > * {\n  min-width: 0;\n}\n\n.section {\n  border-bottom: var(--rule);\n}\n\n\/* The footer draws its own top rule, so the last block in the page column must not\n   draw a bottom one or the hairline doubles above the footer on every page.\n   This was written as `.shell > :has(+ .site-footer)`, which never matched: the\n   footer is a sibling of main.delta-main, not of .shell, so it is not the\n   shell's next element. Closing on :last-child needs no knowledge of what\n   follows the shell. *\/\n.delta-main > :last-child {\n  border-bottom: 0;\n}\n\n.section__inner {\n  padding: var(--layout-section-block) var(--pad);\n}\n\n.section__inner--measure {\n  max-width: var(--layout-content);\n}\n\n\/* Links inside body text only. Never a bare `.x a { color }` (0,1,1): it\n   outranks a component's own color (.btn is 0,1,0) and paints button labels\n   invisible. *\/\n.section__inner a:not([class]) {\n  color: var(--color-action);\n}\n\n\/* The one eyebrow. Every short label that sits above a heading and names what\n   follows uses this and nothing else \u2014 section heads, hero, service bands. It\n   carries its own colour and its own space below, so it works on its own; a\n   block that needs a different layout (an icon beside it, say) adds that and\n   changes nothing about the type. Do not write a second mono variant: the\n   role is the same, so the style is the same. *\/\n.eyebrow {\n  display: block;\n  margin: 0;\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n  line-height: var(--title-2xs-leading);\n  letter-spacing: var(--tracking-wide);\n  font-weight: var(--weight-regular);\n  text-transform: uppercase;\n  color: var(--color-action);\n}\n\n.cluster {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: var(--space-sm);\n}\n\n\/* A row of buttons stacks and goes full width on a narrow screen: side by side\n   they either wrap into a ragged pair or squeeze their labels. Scoped with\n   :has(> .btn) so a cluster of badges or meta keeps flowing as a row. *\/\n@media (max-width: 39.99rem) {\n  .cluster:has(> .btn) {\n    flex-direction: column;\n    align-items: stretch;\n  }\n}\n\n\/* ---- Terminal caption -----------------------------------------------\n   A command line used as a label. It began inside the intake form, then the\n   method grid needed the same idiom, so it moved here rather than being copied\n   \u2014 the same mistake .pgrid made. The host segment carries the accent; the\n   command after it takes the surrounding ink. *\/\n.prompt {\n  margin: 0 0 var(--space-xl);\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n  color: var(--color-ink-muted);\n}\n\n.prompt__host {\n  color: var(--color-action);\n}\n\n\/* The action colour is 3.4:1 on the contrast ground, under the floor. Lifted\n   towards the light ink rather than replaced, so the segment still reads as an\n   accent, and derived from the tokens so it follows a palette change. *\/\n.inverted .prompt__host {\n  color: color-mix(in srgb, var(--color-action), var(--color-ink-on-contrast) 45%);\n}\n\n\/* ---- Ruled cell grid -------------------------------------------------\n   A shared layout utility, not a component: the grid owns every hairline and\n   the cells inside it draw none. Modifier picks the column count at the md\n   breakpoint. The nth-child maths is tied to that count, so changing the\n   number of columns means revisiting the border rules. *\/\n.cells {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: grid;\n  border-top: var(--rule);\n}\n\n.cells > * {\n  border-bottom: var(--rule);\n}\n\n.cells > :last-child {\n  border-bottom: 0;\n}\n\n.secfoot {\n  padding: var(--space-xl) var(--pad);\n  border-top: var(--rule);\n}\n\n.secfoot__link {\n  display: inline-flex;\n  align-items: center;\n  gap: var(--space-2xs);\n  padding-bottom: var(--space-3xs);\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n  color: var(--color-ink);\n  text-decoration: none;\n  border-bottom: var(--border-width) solid var(--color-action);\n}\n\n.secfoot__link:hover {\n  color: var(--color-action);\n}\n\n@media (min-width: 40rem) {\n  .cells--2,\n  .cells--3,\n  .cells--4 {\n    grid-template-columns: repeat(2, 1fr);\n  }\n\n  .cells--2 > * {\n    border-right: var(--rule);\n  }\n\n  .cells--2 > :nth-child(2n) {\n    border-right: 0;\n  }\n\n  .cells--2 > :nth-last-child(-n+2) {\n    border-bottom: 0;\n  }\n\n  .cells--3 > *,\n  .cells--4 > * {\n    border-right: var(--rule);\n  }\n\n  .cells--3 > :nth-child(2n),\n  .cells--4 > :nth-child(2n) {\n    border-right: 0;\n  }\n\n  .cells--3 > :last-child,\n  .cells--4 > :last-child {\n    border-bottom: var(--rule);\n  }\n}\n\n@media (min-width: 64rem) {\n  .cells--3 {\n    grid-template-columns: repeat(3, 1fr);\n  }\n\n  .cells--3 > :nth-child(2n) {\n    border-right: var(--rule);\n  }\n\n  .cells--3 > :nth-child(3n) {\n    border-right: 0;\n  }\n\n  .cells--3 > :nth-last-child(-n+3) {\n    border-bottom: 0;\n  }\n\n  .cells--4 {\n    grid-template-columns: repeat(4, 1fr);\n  }\n\n  .cells--4 > :nth-child(2n) {\n    border-right: var(--rule);\n  }\n\n  .cells--4 > :nth-child(4n) {\n    border-right: 0;\n  }\n\n  \/* Matches the .cells--3 form above, and it has to: `.cells--4 > *` is 0,1,0\n     and loses to the `:last-child` rule at the sm breakpoint, which left the\n     fourth cell drawing a bottom rule against whatever followed the grid. *\/\n  .cells--4 > :nth-last-child(-n+4) {\n    border-bottom: 0;\n  }\n}\n\n\/* ---- Inverted context ------------------------------------------------\n   color must be declared here: it inherits from body as an already computed\n   value, so rebinding --color-ink alone leaves descendants on the light ink. *\/\n.inverted {\n  color: var(--color-ink);\n  background: var(--color-surface-contrast);\n  --color-ink: var(--color-ink-on-contrast);\n  --color-ink-muted: var(--color-ink-muted-on-contrast);\n  --color-border: var(--color-border-on-contrast);\n  --color-surface-subtle: color-mix(in srgb, var(--color-surface-contrast), white 7%);\n  \/* action, action-hover and on-action are deliberately NOT rebound: a filled\n     button carries its own ground, so it reads the same here as on a light\n     section. Only bare text links need help \u2014 the brand colour is 3.4:1 on this\n     ground, so they take the light ink instead (see the rule below). *\/\n  --color-focus: var(--color-ink-on-contrast);\n}\n\n\/* The eyebrow is action-coloured on a light ground, which is 3.4:1 on this one\n   \u2014 under the 4.5 floor. It takes the light ink here for the same reason bare\n   links below do. The icon inside it follows, because it inherits currentColor. *\/\n.inverted .eyebrow {\n  color: var(--color-ink-on-contrast);\n}\n\n\/* Unclassed links only. A classed element \u2014 a button \u2014 keeps its own colours,\n   which is what makes the filled button identical on light and inverted grounds. *\/\n.inverted a:not([class]) {\n  color: var(--color-ink-on-contrast);\n}\n\n.inverted a:not([class]):where(:hover) {\n  color: var(--color-ink-muted-on-contrast);\n}\n\n\/* ---- Ruled post grid -------------------------------------------------\n   Shared utility, not a component: used by the blog archive and by the related\n   block on a single post. It lived in the archive template CSS, which does not\n   load on a single, so the related grid rendered unstyled. The grid owns every\n   hairline and the cards inside draw none. *\/\n.pgrid {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: grid;\n  border-top: var(--rule);\n}\n\n.pgrid > * {\n  border-bottom: var(--rule);\n}\n\n.pgrid > :last-child {\n  border-bottom: 0;\n}\n\n\/* The final row draws no bottom rule: the section around the grid closes it,\n   the same arrangement .cells uses. Re-adding a rule on the last cell alone\n   doubled the hairline against the section's own. The nth-last-child count is\n   tied to the column count, so changing one means changing the other. *\/\n@media (min-width: 40rem) {\n  .pgrid {\n    grid-template-columns: repeat(2, 1fr);\n  }\n\n  .pgrid > * {\n    border-right: var(--rule);\n  }\n\n  .pgrid > :nth-child(2n) {\n    border-right: 0;\n  }\n\n  .pgrid > :nth-last-child(-n+2) {\n    border-bottom: 0;\n  }\n}\n\n@media (min-width: 64rem) {\n  .pgrid {\n    grid-template-columns: repeat(3, 1fr);\n  }\n\n  .pgrid > :nth-child(2n) {\n    border-right: var(--rule);\n  }\n\n  .pgrid > :nth-child(3n) {\n    border-right: 0;\n  }\n\n  .pgrid > :nth-last-child(-n+3) {\n    border-bottom: 0;\n  }\n}\n\n\/* ---- Pager -----------------------------------------------------------\n   Shared utility, not a component. It was written three times \u2014 in the blog\n   archive, the term archive and the search results template \u2014 and the copies\n   had already drifted apart (two on --space-sm, one on --gap-inline) before\n   anyone noticed, which is the same way .pgrid went wrong. It sits here beside\n   .pgrid because every template that lists posts also pages them.\n   --gap-inline is the right name for it: these are items sitting in a row. *\/\n.pager {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  gap: var(--gap-inline);\n  padding: var(--space-xl) var(--pad);\n  border-top: var(--rule);\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n}\n\n\/* :empty does not match here \u2014 the pagination loop leaves whitespace behind\n   even when it renders no links, which is enough to defeat it. Test for the\n   links themselves, or an empty band with a rule above it sits under the grid. *\/\n.pager:not(:has(a)) {\n  display: none;\n}\n\n.pager__n {\n  display: inline-grid;\n  place-items: center;\n  min-inline-size: var(--space-xl);\n  padding: var(--space-2xs) var(--space-xs);\n  border: var(--rule);\n  color: var(--color-ink-muted);\n  text-decoration: none;\n}\n\n.pager__n:hover {\n  color: var(--color-action);\n  border-color: var(--color-action);\n}\n\n.pager__n[aria-current] {\n  background: var(--color-action);\n  border-color: var(--color-action);\n  color: var(--color-on-action);\n}\n\n\/* ---- Form controls ---------------------------------------------------\n   The field primitives \u2014 .field, .field__lbl, .field__in and the rest \u2014 live\n   on the `field` component, not here. They were written in both files, and\n   this copy loaded last and won, so editing the component recipe changed\n   nothing on the page and only its custom select arrow ever reached the\n   screen. Component CSS applies by class across the whole site, with no\n   data-delta-component marker needed, so the search bar below takes the same\n   controls from the component. Only what is not the control stays here. *\/\n\n\/* A single control beside its submit. Stacks below sm, where a button sitting\n   next to a full-width input leaves neither enough room. *\/\n.searchbar {\n  display: grid;\n  gap: var(--space-sm);\n  max-width: var(--line-length-lg);\n}\n\n@media (min-width: 40rem) {\n  .searchbar {\n    grid-template-columns: 1fr auto;\n    align-items: end;\n  }\n\n  .searchbar .field {\n    grid-column: 1;\n  }\n}\n\n\/* ---- Page figure -----------------------------------------------------\n   A full-bleed band under a page title. Shared: the services page and the blog\n   archive both use it, so it lives here rather than in either one.\n\n   Full-bleed means the inner edge of the page column (.delta-main), not the\n   viewport \u2014 its side rules are the edge of the design. The figure takes\n   no --pad, so it runs rule to rule.\n\n   A fixed ratio with object-fit: cover, because the source images are 16:9 and\n   the band is wider than that; an auto ratio would let the band's height follow\n   whatever image is dropped in. Shorter ratio on narrow screens, where a 16:5\n   crop leaves nothing readable in the frame. *\/\n.pagefig {\n  margin: 0;\n  aspect-ratio: 16 \/ 9;\n  overflow: hidden;\n  background: var(--color-surface-subtle);\n  border-bottom: var(--rule);\n}\n\n.pagefig img {\n  display: block;\n  inline-size: 100%;\n  block-size: 100%;\n  object-fit: cover;\n  object-position: center;\n}\n\n\/* Below md the band leads the page: the image comes first, then the title and\n   lead below it. order:-1 needs a flex context, and the section is a plain\n   block, so :has() gives one only to the sections that carry a page figure.\n   The rule moves to the block end for the same reason \u2014 the figure is now the\n   first thing under the header, not the last thing under the copy. *\/\n@media (max-width: 39.99rem) {\n  .section:has(> .pagefig) {\n    display: flex;\n    flex-direction: column;\n  }\n\n  .pagefig {\n    order: -1;\n    border-bottom: 0;\n    border-top: var(--rule);\n  }\n}\n\n@media (min-width: 40rem) {\n  .pagefig {\n    aspect-ratio: 16 \/ 5;\n  }\n}\n\n\/* ---- Closing call to action -----------------------------------------\n   Shared utility. It began in the Services page CSS; the Case study page\n   needed the same block, so it moved here rather than being copied \u2014 the\n   same mistake .pgrid and .pager made. The title cap moved from a bare 20ch\n   to --line-length-title, the lead cap from 46ch to --line-length-md. *\/\n.cta {\n  display: grid;\n  gap: var(--space-lg);\n  padding: var(--space-3xl) var(--pad);\n  align-items: center;\n}\n\n.cta__title {\n  margin: 0;\n  font-family: var(--font-title);\n  font-size: var(--title-lg-size);\n  line-height: var(--title-lg-leading);\n  letter-spacing: var(--title-lg-tracking);\n  font-weight: var(--weight-bold);\n  max-width: var(--line-length-title);\n  text-wrap: balance;\n}\n\n.cta__lead {\n  margin: var(--space-md) 0 0;\n  max-width: var(--line-length-md);\n  color: var(--color-ink-muted);\n}\n\n\/* Stacked, and both buttons the same width: min-inline-size sets the floor\n   and the wider label sets the rest, so the pair reads as one block. *\/\n.cta__actions {\n  display: flex;\n  flex-direction: column;\n  align-items: stretch;\n  gap: var(--space-sm);\n  min-inline-size: 16rem;\n}\n\n@media (min-width: 64rem) {\n  .cta {\n    grid-template-columns: 1fr auto;\n    gap: var(--space-2xl);\n  }\n}\n\n\/* Dot grid behind the call to action, on a pseudo-element so the mask fades\n   only the grid and not the section ground or its text. isolation keeps the\n   negative z-index inside this section. Dot colour is mixed from the section's\n   own ink, so a token change moves it. *\/\n.section:has(> .cta) {\n  position: relative;\n  isolation: isolate;\n}\n\n.section:has(> .cta)::before {\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  z-index: -1;\n  pointer-events: none;\n  background-image: radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--color-ink-on-contrast) 16%, transparent) 1px, transparent 0);\n  background-size: var(--space-xl) var(--space-xl);\n  -webkit-mask-image: radial-gradient(120% 120% at 100% 0%, black 20%, transparent 72%);\n  mask-image: radial-gradient(120% 120% at 100% 0%, black 20%, transparent 72%);\n}\n\n\/* Contained to the same measure as the page column (.delta-main), with the same side rules, so the\n   bar reads as the top of the page column rather than a band behind it. The\n   footer does the same at the other end. *\/\n.site-header {\n  position: sticky;\n  top: 0;\n  z-index: 20;\n  display: flex;\n  align-items: center;\n  gap: var(--space-md);\n  inline-size: 100%;\n  max-width: var(--layout-max);\n  margin-inline: auto;\n  padding: var(--space-sm) var(--pad);\n  border-inline: var(--rule);\n  border-bottom: var(--rule);\n  background: var(--color-surface-body);\n}\n\n\/* Mixed in srgb, not oklch. Mixing a warm near-white with transparent in oklch\n   leaves the hue channel powerless \u2014 the computed value came out as\n   `oklch(0.9855 0.0057 none \/ 0.92)`, and a residual chroma on an undefined hue\n   renders pink, so the bar read visibly cooler and pinker than the page it sits\n   on. srgb has no hue channel to lose and holds the cream. *\/\n@supports (backdrop-filter: blur(2px)) {\n  .site-header {\n    background: color-mix(in srgb, var(--color-surface-body), transparent 8%);\n    backdrop-filter: blur(8px);\n  }\n}\n\n\/* The bar keeps the tighter button. The component's block padding is sized for\n   a button sitting in a page, which would make the header noticeably taller. *\/\n.site-header .btn {\n  padding-block: var(--space-sm);\n}\n\n.site-header__brand {\n  display: flex;\n  align-items: center;\n  gap: var(--space-xs);\n  margin-right: auto;\n  text-decoration: none;\n  color: var(--color-ink);\n}\n\n.site-header__mark {\n  display: grid;\n  place-items: center;\n  inline-size: var(--space-xl);\n  block-size: var(--space-xl);\n  background: var(--color-action);\n  color: var(--color-on-action);\n  font-family: var(--font-title);\n  font-size: var(--text-sm-size);\n  font-weight: var(--weight-bold);\n}\n\n.site-header__word {\n  font-family: var(--font-title);\n  font-size: var(--title-xs-size);\n  font-weight: var(--weight-bold);\n  letter-spacing: var(--tracking-tight);\n}\n\n\/* Below the md breakpoint the links become a disclosure panel dropped from the\n   bar. The panel is absolute against the sticky bar, which already establishes\n   the containing block \u2014 making the bar static drops it to the top of the page. *\/\n.site-header__nav {\n  display: none;\n  position: absolute;\n  inset-inline: 0;\n  top: 100%;\n  background: var(--color-surface-body);\n  border-bottom: var(--rule);\n}\n\n\/* The panel can outrun a short viewport once the links are set this large, so\n   it caps at the space under the bar and scrolls inside itself. *\/\n.site-header__nav.is-open {\n  display: block;\n  max-block-size: calc(100dvh - var(--space-4xl));\n  overflow-y: auto;\n}\n\n\/* primary_nav emits its own ul\/li\/a, so style by descent, never by adding\n   classes inside the placeholder. The :not([class]) guard keeps this off any\n   classed link \u2014 a bare `.x a { color }` is 0,1,1 and outranks .btn at 0,1,0. *\/\n.site-header__nav ul {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n}\n\n\/* On the panel the links are the page, not a strip of labels, so they take the\n   heading face at the h3 step. Above md they drop back to reading size in the\n   bar. Navigation is reading text either way \u2014 the mono face is reserved for\n   metadata: dates, counts, field labels, the terminal caption. *\/\n.site-header__nav li a:not([class]) {\n  display: block;\n  padding: var(--space-md) var(--pad);\n  border-top: var(--rule);\n  font-family: var(--font-title);\n  font-size: var(--title-md-size);\n  line-height: var(--title-md-leading);\n  letter-spacing: var(--title-md-tracking);\n  font-weight: var(--weight-semibold);\n  color: var(--color-ink);\n  text-decoration: none;\n}\n\n\/* The call to action lives at the foot of the panel on a small screen, where\n   the bar has no room for it, and full width so it reads as the end of the\n   list rather than a stray control. *\/\n.site-header__navcta {\n  padding: var(--space-lg) var(--pad) var(--space-xl);\n  border-top: var(--rule);\n}\n\n.site-header__navcta .btn {\n  inline-size: 100%;\n}\n\n\/* The bar's own copy of the button is for md and up; below that the panel\n   carries it and two would be one too many. *\/\n.site-header__cta {\n  display: none;\n}\n\n.site-header__nav li:first-child a:not([class]) {\n  border-top: 0;\n}\n\n.site-header__nav li a:not([class]):hover,\n.site-header__nav li a:not([class])[aria-current] {\n  color: var(--color-action);\n}\n\n.site-header__toggle {\n  appearance: none;\n  background: none;\n  border: 0;\n  padding: var(--space-2xs);\n  display: grid;\n  place-items: center;\n  cursor: pointer;\n  color: var(--color-ink);\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n}\n\n.site-header__toggle:hover {\n  color: var(--color-action);\n}\n\n.site-header__toggle .is-close { display: none; }\n.site-header__toggle[aria-expanded=\"true\"] .is-open { display: none; }\n.site-header__toggle[aria-expanded=\"true\"] .is-close { display: inline; }\n\n@media (min-width: 64rem) {\n  .site-header__toggle {\n    display: none;\n  }\n\n  .site-header__cta {\n    display: inline-flex;\n  }\n\n  .site-header__navcta {\n    display: none;\n  }\n\n  .site-header__nav {\n    display: block;\n    position: static;\n    border-bottom: 0;\n    background: none;\n  }\n\n  .site-header__nav ul {\n    flex-direction: row;\n    gap: var(--space-lg);\n  }\n\n  .site-header__nav li a:not([class]) {\n    padding: 0;\n    border-top: 0;\n    font-family: var(--font-text);\n    font-size: var(--text-sm-size);\n    line-height: var(--text-md-leading);\n    letter-spacing: var(--text-sm-tracking);\n    font-weight: var(--weight-regular);\n  }\n}\n\n\/* Contained to the same measure as the page column (.delta-main), with the same side rules, so the\n   page column runs unbroken from the header to the bottom of the footer. *\/\n.site-footer {\n  display: grid;\n  gap: var(--space-xl);\n  inline-size: 100%;\n  max-width: var(--layout-max);\n  margin-inline: auto;\n  padding: var(--space-2xl) var(--pad);\n  border-inline: var(--rule);\n  border-top: var(--rule);\n}\n\n.site-footer__brand {\n  display: grid;\n  gap: var(--space-xs);\n  align-content: start;\n}\n\n.site-footer__word {\n  font-family: var(--font-title);\n  font-size: var(--title-xs-size);\n  font-weight: var(--weight-bold);\n  letter-spacing: var(--tracking-tight);\n  color: var(--color-ink);\n}\n\n.site-footer__line {\n  margin: 0;\n  max-width: var(--line-length-xs);\n  font-size: var(--text-sm-size);\n  line-height: var(--text-sm-leading);\n  color: var(--color-ink-muted);\n}\n\n.site-footer__col {\n  display: grid;\n  gap: var(--space-2xs);\n  align-content: start;\n}\n\n.site-footer__h {\n  margin: 0 0 var(--space-2xs);\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n  text-transform: uppercase;\n  letter-spacing: var(--tracking-wide);\n  color: var(--color-ink);\n}\n\n\/* footer_nav emits its own list markup, so the column styles by descent. The\n   :not([class]) guard keeps this rule off any classed link. *\/\n.site-footer__col ul {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: grid;\n  gap: var(--space-2xs);\n}\n\n\/* Matches the header: navigation is reading text and takes the text face. The\n   mono face stays on the column headings and the fine print, which are labels. *\/\n.site-footer__col li a:not([class]) {\n  font-family: var(--font-text);\n  font-size: var(--text-sm-size);\n  color: var(--color-ink-muted);\n  text-decoration: none;\n}\n\n.site-footer__col li a:not([class]):hover {\n  color: var(--color-action);\n}\n\n.site-footer__fine {\n  margin: 0;\n  padding-top: var(--space-lg);\n  border-top: var(--rule);\n  font-family: var(--font-mono);\n  font-size: var(--mono-sm);\n  color: var(--color-ink-muted);\n}\n\n@media (min-width: 40rem) {\n  .site-footer {\n    grid-template-columns: 2fr 1fr 1fr;\n  }\n\n  .site-footer__fine {\n    grid-column: 1 \/ -1;\n  }\n}"}],"mode":"seed"},"_links":{"self":[{"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/pages\/21","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/comments?post=21"}],"version-history":[{"count":5,"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/pages\/21\/revisions"}],"predecessor-version":[{"id":147,"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/pages\/21\/revisions\/147"}],"wp:attachment":[{"href":"https:\/\/preview.deltatheme.com\/kiln\/wp-json\/wp\/v2\/media?parent=21"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}