/*!*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/[locale]/layout.tsx","import":"Inter","arguments":[{"subsets":["latin"],"variable":"--font-sans"}],"variableName":"sans"} ***!
  \*************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* cyrillic-ext */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/ba9851c3c22cd980-s.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/21350d82a1f187e9-s.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/c5fe6dc8356a8c31-s.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/19cfc7226ec3afaa-s.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/df0a9ae256c0569c-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/8e9860b6e62d6359-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: '__Inter_f367f3';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/e4af272ccee01ff0-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: '__Inter_Fallback_f367f3';src: local("Arial");ascent-override: 90.49%;descent-override: 22.56%;line-gap-override: 0.00%;size-adjust: 107.06%
}.__className_f367f3 {font-family: '__Inter_f367f3', '__Inter_Fallback_f367f3';font-style: normal
}.__variable_f367f3 {--font-sans: '__Inter_f367f3', '__Inter_Fallback_f367f3'
}

/*!***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/[locale]/layout.tsx","import":"Space_Grotesk","arguments":[{"subsets":["latin"],"variable":"--font-display"}],"variableName":"display"} ***!
  \***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* vietnamese */
@font-face {
  font-family: '__Space_Grotesk_dd5b2f';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(/_next/static/media/e1aab0933260df4d-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: '__Space_Grotesk_dd5b2f';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(/_next/static/media/b7387a63dd068245-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: '__Space_Grotesk_dd5b2f';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url(/_next/static/media/36966cca54120369-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: '__Space_Grotesk_Fallback_dd5b2f';src: local("Arial");ascent-override: 89.71%;descent-override: 26.62%;line-gap-override: 0.00%;size-adjust: 109.69%
}.__className_dd5b2f {font-family: '__Space_Grotesk_dd5b2f', '__Space_Grotesk_Fallback_dd5b2f';font-style: normal
}.__variable_dd5b2f {--font-display: '__Space_Grotesk_dd5b2f', '__Space_Grotesk_Fallback_dd5b2f'
}

/*!*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/[locale]/layout.tsx","import":"Archivo","arguments":[{"subsets":["latin","latin-ext","vietnamese"],"axes":["wdth"],"display":"swap","variable":"--font-archivo"}],"variableName":"archivo"} ***!
  \*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* vietnamese */
@font-face {
  font-family: '__Archivo_9e22fe';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(/_next/static/media/8a053b136321ec99-s.p.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: '__Archivo_9e22fe';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(/_next/static/media/2a8fe189f1a8dd0c-s.p.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: '__Archivo_9e22fe';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(/_next/static/media/c214ffb7f5362987-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: '__Archivo_Fallback_9e22fe';src: local("Arial");ascent-override: 88.96%;descent-override: 21.28%;line-gap-override: 0.00%;size-adjust: 98.70%
}.__className_9e22fe {font-family: '__Archivo_9e22fe', '__Archivo_Fallback_9e22fe';font-style: normal
}.__variable_9e22fe {--font-archivo: '__Archivo_9e22fe', '__Archivo_Fallback_9e22fe'
}

/*!***************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[12].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[12].use[3]!./styles/tokens.css ***!
  \***************************************************************************************************************************************************************************************************************************************************************/
/* EchoPage design tokens — v2.0 "Kinetic Type".
   Source of truth: docs/echopage-design-system.md.

   This file is deliberately plain CSS with no Tailwind syntax, because it has
   THREE consumers and only one of them has a build step:
     1. app/globals.css        — imports it
     2. tailwind.config.ts     — references these variables by name
     3. HtmlProfileRenderer    — will embed this block verbatim into the
                                 published artifact, where there is no bundler
   Never hardcode a hex anywhere else. If a value is missing here, add it here. */

:root {
  /* ---- two themes, and the light one is written here in full -------------
     Chosen 2026-08-24, and saturated a step on 2026-08-25. Light is
     "Аэрофлот": a cool grey-blue ground, an ink that is blue-black rather than
     neutral, one institutional blue for the action and кумач for the alarm.

     The first cut was too quiet to work. Its fields sat 1.28:1 from the ground
     — enough for the seam rule to be legible, not enough for a section to read
     as a section, so whole blocks dissolved into the page they were meant to
     stand on. The ground moved a step lighter and cooler, which gives the
     fields somewhere to stand, and the fields took roughly double their
     saturation at the same hue: the separation is now 1.46 to 1.57, and the
     accent carries text at 5.71:1 rather than scraping 4.63. Dark is "Полночь", and it lives in the
     media query at the bottom of this block — as a redefinition of these same
     tokens and nothing else.

     That split is the whole discipline. Every colour on the site is stated
     once, here, as a ROLE; no component names a value; and the dark theme is
     therefore a list of twenty numbers rather than a second stylesheet. The
     handful of rules that are genuinely structural rather than chromatic —
     which end of the ladder the deep band sits at — live in poster.css under
     the same query, and there are eight of them.

     --ink is #1b2a33, not #000 and not a neutral charcoal. The ground is a
     cool grey and a neutral black on it reads as a hole punched through; a
     blue-black reads as the same material gone dark. 11.28:1 on the ground. */
  --ink: #16242d;
  --paper: #e9eef2;

  /* ---- surfaces: the ground, a card, a card on a card -------------------- */
  --surface: #f5f8fa;
  --surface-hi: #fcfdfe;

  /* ---- edges -------------------------------------------------------------
     --edge is decoration and may be quiet. --edge-strong is the boundary of a
     CONTROL — input, select, unfilled button — which WCAG 1.4.11 holds to 3:1
     against its surroundings: 3.08:1 on the ground, 3.34:1 on a card. */
  --edge: #bcc7ce;
  --edge-strong: #6e7d85;

  /* ---- text --------------------------------------------------------------
     --text-mute is measured against the DARKEST field, not against the ground:
     it has 6.71:1 to spare on the ground and only 4.62:1 on --fill-accent.
     Choose it on the ground alone and every caption inside a coloured section
     fails. --text-faint is deliberately not held to that — it clears AA on the
     ground and on cards, which is everywhere it is used, and it does not go
     inside a colour field. */
  --text-mute: #39505c;
  --text-faint: #546772;

  /* ---- accent: one blue, two values --------------------------------------
     --accent is the MARK — link, chart stroke, underline, focus ring — and
     carries text itself at 4.63:1 on the ground. --accent-fill is the same hue
     deeper and is the only one a light label may sit on, 7.09:1. A primary
     button whose own label is the near miss is the one thing on a page that
     cannot be allowed to fail, which is why these are two tokens and not one. */
  --accent: #0f5f9e;
  --accent-fill: #0d4d80;
  --accent-deep: #0a3d67;
  --on-accent: #fcfdfe;

  /* Ochre — the second series on the visibility chart. It separates from
     --accent by hue and by the dash pattern the chart already draws, so two
     lines stay two lines for a reader who cannot tell them apart by colour. */
  --accent-2: #7a5b12;

  /* Кумач, at FIELD scale only: the block that names a commercial
     relationship. --bad below is the same family at MARK scale — one word, not
     a section — which is the split this system has always run on. */
  --signal: #b0201a;

  /* ---- the fields --------------------------------------------------------
     Whole blocks flooded, ink lettering on top. Named for the JOB, never the
     hue: a token called `lime` holding a blue is the trap this file has been
     burned by twice. ink measures 8.06 / 9.09 / 8.72 on them, and each clears
     1.25:1 against the ground so the seam between two sections is visible
     before the rule between them is read. */
  --fill-accent: #9ac5e3;
  --fill-person: #d9c49e;
  --fill-info: #afcbbb;

  /* ---- the two gradients, and there are only two ------------------------
     Near-flat by design: one step of the action colour, and light falling
     across the ground. A visible ramp would be the one gesture that belongs to
     a different decade than everything else here. Both are declared as tokens
     so a third cannot quietly appear at a call site, and every surface that
     uses one also states a flat colour underneath it — a gradient is a
     background-IMAGE, dropped on print, replaced under forced colours, and
     absent for the moment before it paints. */
  --grad-cta: linear-gradient(100deg, var(--accent-fill), var(--accent-deep));
  --grad-hero: linear-gradient(150deg, var(--surface-hi) 0%, var(--paper) 54%, var(--fill-accent) 260%);

  /* ---- the structural half of the theme, and it is values too -------------
     These eight exist so the dark theme is a token block and nothing else.

     They name the one thing that is not a colour swap but a decision about
     WHICH END OF THE LADDER a surface sits at. On this page the deep band is
     the ink itself; on the dark one ink is the LETTERING, and a band painted
     in it would be a white slab across the page — so --band moves and the four
     surfaces that borrow it move with it. Written as rules instead, every one
     of them would need a second copy under `[data-theme]` the moment a toggle
     existed, and there is now a toggle. */
  --band: var(--ink);
  --on-band: var(--paper);

  /* The header, on this theme only, is warm rather than deep.
     A separate token from --band because --band is shared by the ticker and
     three section floods; re-pointing it would have repainted all of them to
     move one bar.

     THIS IS THE ONE VALUE. --nav-glass below is derived from it rather than
     written out a second time, and that is not tidiness: the two WERE written
     separately, `.ep-nav` painted the glass over `.b-nav`'s ground because it
     is declared later at equal specificity, and the light theme shipped a
     header with ink lettering on a deep glass. Everything about the bar said
     warm except the pixels. A derived value cannot drift from its source.

     Contrast: #F3E9D7 against --ink #16242d is roughly 14:1, comfortably past
     AAA for body text, so the header keeps ink lettering rather than needing a
     second decision about what sits on it. At the glass alpha, over the darkest
     thing this bar can scroll across, it still measures 8.89:1. */
  --nav-band: #f3e9d7;
  --on-nav-band: var(--ink);

  /* A pale header takes the ordinary ink-outside/paper-inside ring. The swapped
     pair exists for deep grounds and would put a pale ring on a pale bar. */
  --nav-focus-outer: var(--ink);
  --nav-focus-inner: var(--paper);

  /* backdrop-filter needs a ground that is already translucent, and var()
     cannot add alpha to a hex — color-mix can, which is what lets the alpha and
     the colour stop being two independent decisions. 0.80 measured over the
     worst case the header can scroll across, in both themes.

     The hair follows the ground rather than being fixed: a pale hairline is
     invisible on a cream bar, which is how a rule meant to mark the bottom edge
     of the header stopped marking anything. */
  --nav-glass: color-mix(in srgb, var(--nav-band) 80%, transparent);
  --nav-hair: color-mix(in srgb, var(--on-nav-band) 26%, transparent);

  /* The bar where it lands ON a dark flood. The rule it serves is the system's
     oldest: the action is always the opposite of its ground. */
  --bar-flood: var(--paper);
  --bar-flood-label: var(--ink);

  /* The focus pair inside the dark floods, where the base ink ring is nothing. */
  --focus-flood-outer: var(--paper);
  --focus-flood-inner: var(--ink);

  /* The dead half of the without/with pair: the darkest thing on a light page. */
  --vs-dead: color-mix(in srgb, var(--ink) 88%, var(--paper));
  --vs-dead-ink: var(--paper);

  /* ---- work register neutrals -------------------------------------------- */
  --w-bg: #e9eef2;
  --w-panel: #f5f8fa;
  --w-line: #6e7d85;
  --w-hair: rgba(22, 36, 45, 0.18);
  --w-mute: #39505c;
  --w-faint: #546772;

  /* ---- status ------------------------------------------------------------- */
  --ok: #1f6b41;
  --warn: #775611;
  --bad: #a51b14;

  /* ---- type: Latin + Vietnamese only. Other scripts pair a companion face,
         selected by :lang() — see design-system §8.2. ------------------------ */
  /* Namespaced --ep-* on purpose: next/font already owns --font-display and
     --font-sans on <body>, and silently shadowing those would be a trap. */
  --ep-display:
    var(--font-archivo), "Archivo", "Space Grotesk", "Helvetica Neue",
    "Arial Black", Helvetica, Arial, sans-serif;
  --ep-ui:
    var(--font-sans), "Space Grotesk", "Archivo", "Helvetica Neue", Helvetica,
    Arial, "Segoe UI", Roboto, system-ui, sans-serif;
  --ep-mono:
    ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono",
    monospace;

  /* Poster ramp. Tracking tightens as the size grows. */
  --d0-size: clamp(52px, 15vw, 230px);
  --d1-size: clamp(40px, 12vw, 168px);
  --d2-size: clamp(30px, 8vw, 96px);
  --d3-size: clamp(22px, 4.6vw, 52px);
  --d4-size: clamp(18px, 2.6vw, 30px);
  --lead-size: clamp(17px, 2.1vw, 25px);

  --d0-lh: 0.84;
  --d1-lh: 0.86;
  --d2-lh: 0.92;
  --d3-lh: 1;
  --d4-lh: 1.08;
  /* 1.5 is the floor for body leading at a phone measure of ~44 characters.
     Was 1.38, which is a display value applied to reading text. */
  --lead-lh: 1.5;

  --d0-track: -0.05em;
  --d1-track: -0.045em;
  --d2-track: -0.035em;
  --d3-track: -0.025em;
  --d4-track: -0.02em;

  /* Work ramp. */
  --wh1-size: clamp(24px, 3.4vw, 38px);
  --wh2-size: clamp(17px, 2vw, 22px);
  /* Was 15px — SMALLER than the body text it introduces, which is the step that
     stops an owner finding the section they came to edit. A subheading has to
     outrank its own paragraph, so size goes above --w-body-size and weight
     carries the rest. */
  --wh3-size: 1.125rem;
  /* 16px, and the same at every width. 14.5px is below the size iOS treats as
     small enough to zoom a focused field to, and this register is where an
     owner reads and edits their own profile copy on a phone. */
  --w-body-size: 16px;
  --w-body-lh: 1.5;
  /* rem, not px: this is reading text at the bottom of the reading range, so it
     has to follow a browser font-size the visitor set for themselves. */
  --w-small-size: 0.875rem;
  --w-label-size: 10.5px;
  --w-label-track: 0.2em;

  /* ---- layout ------------------------------------------------------------- */
  --gut: clamp(16px, 4.4vw, 64px);
  /* Measured, not guessed: 8px padding-block x2 + a 44px control + the 2px
     rule = 62px. `scroll-margin-block-start` in globals.css is derived from
     this, so a wrong value parks an anchor target under the sticky header. */
  --nav-h: 62px;
  --rule: 2px;

  /* The system's ONE radius, and it belongs to one thing: the panel. A second
     value would be a second register, and a page with two radii reads as two
     design systems sharing a stylesheet. Everything else in here — the bar, the
     field, the chip, the rank strip, the state square — stays square-cornered,
     because the 2px rule is what draws an edge in this language and a rounded
     rule is a different edge.
     12px is measured against the panel's own padding, clamp(18px,2.6vw,30px):
     it is visible at 390px, where the panel is 356px wide, without eating the
     corner of the border it is rounding.
     There is deliberately no --shadow-panel beside it. A panel here separates
     with a 2px ink border at 18.10:1 on paper; a soft shadow under that border
     adds a second, weaker edge saying the same thing, and on the paper flood it
     would be the only soft-edged object on the page. If a later panel genuinely
     needs depth, one token goes here — not a second one at the call site. */
  --r-panel: 12px;

  /* ---- motion: three durations, named for what is moving ------------------
     Every transition in this system picks one of these. Ad-hoc values (0.18s,
     0.35s, 0.38s) were the reason the same kind of change felt like a different
     interface depending on which file it lived in. --ease-out decelerates: the
     thing arrives and stops, which is what a state change should look like.
     There was a third, --dur-tap at 120ms, and nothing ever transitioned on it:
     a press in this system is a fill swap with no travel. Named-but-unused is
     worse than absent here, because this block ships verbatim into the published
     artifact, where an unused custom property is bytes on a stranger's page. */
  --dur-state: 200ms;
  --dur-field: 320ms;
  --ease-out: cubic-bezier(0, 0, 0.2, 1);

  /* The third duration, and the one outlier in kind: --dur-state and
     --dur-field time a change that arrives and stops, while this times one full
     lap of the assistant strip. It is three orders of magnitude longer because
     it is measured against reading speed, not against a fingertip. One lap is
     one lane of thirteen names: 1318px measured at 390px, which is 31px per
     second, rising to about 2610px past 1111px of viewport, where the name size
     caps at 40px — 62px per second. Both are slow enough to read a name as it
     passes, and the strip is slower where the screen is smaller, which is the
     right way round. It lives here rather than in the keyframe so the pace is
     tunable next to the other two instead of being hunted for inside an
     animation shorthand. */
  --dur-ticker: 42s;

  /* ---- focus: a ring on a ring, the only pair that clears 3:1 on all seven
         fills including yellow and lime ------------------------------------- */
  --focus-outer: var(--ink);
  --focus-inner: var(--paper);
  --focus-width: 3px;

  /* ---- variable-font axes. Archivo's real range is wght 100..900,
         wdth 62..125. The kinetic engine clamps to these; nothing may
         write outside them. ------------------------------------------------- */
  --kin-wght-min: 100;
  --kin-wght-max: 900;
  --kin-wdth-min: 62;
  --kin-wdth-max: 125;
  --wght: 800;
  --wdth: 112;
}

/* ---- "Полночь": the dark theme, and only the values change ---------------
   Twenty numbers. No component in this system names a colour, so this block is
   the entire chromatic half of the theme; the eight structural rules that
   cannot be expressed as a value live in poster.css under the same query.

   It is not an inversion of the light set. A dark ground needs its own
   decisions: --accent goes UP two steps because a link has to lift off navy
   rather than sink into paper, --accent-fill goes down because a white label
   now sits on it, and the status trio is re-picked entirely — the light one
   measured 2.58–3.57:1 here, all three below AA and the one that matters most
   the worst of them.

   The fields are the largest departure. On a light page a field is a pastel
   with ink on it; on this one a pastel slab would be a searchlight at 10–12:1,
   so a field becomes a tinted SURFACE and the lettering stays light. Same
   role, same class names, opposite construction. */
@media (prefers-color-scheme: dark) {
  /* :not([data-theme="light"]) so that a visitor who has chosen light in the
     header beats a dark operating system. Without it the toggle would work in
     one direction only. */
  :root:not([data-theme="light"]) {
      --ink: #e6e8ed;
      --paper: #282c34;
      --surface: #323741;
      --surface-hi: #3c424e;
      --edge: #505866;
      --edge-strong: #929bab;
      --text-mute: #bec5d0;
      --text-faint: #abb4c2;
      --accent: #a5c7ef;
      --accent-fill: #a5c7ef;
      --accent-deep: #bed8f5;
      --on-accent: #202832;
      --accent-2: #a3d5cf;
      --signal: #c4b0e8;
      --fill-accent: #384658;
      --fill-person: #494151;
      --fill-info: #354b50;
      --w-bg: #282c34;
      --w-panel: #323741;
      --w-line: #929bab;
      --w-hair: rgba(230, 232, 237, 0.16);
      --w-mute: #bec5d0;
      --w-faint: #abb4c2;
      --ok: #b4d6ad;
      --warn: #e8cb99;
      --bad: #e6a5ab;

      --band: var(--surface-hi);
      --on-band: var(--ink);
      /* Deep here, and named rather than inherited, so the derived glass and
         hair above resolve against it. --paper is the dark theme's ground. */
      --nav-band: var(--paper);
      --on-nav-band: var(--ink);
      --bar-flood: var(--accent-fill);
      --bar-flood-label: var(--on-accent);
      --focus-flood-outer: var(--ink);
      --focus-flood-inner: var(--paper);
      /* Lifted rather than sunk: here the darkest thing on screen is the page. */
      --vs-dead: var(--surface);
      --vs-dead-ink: var(--text-mute);
  }
}

/* The same set again, keyed off the header toggle so an explicit dark choice
   beats a light operating system.
   Stated twice on purpose: a rule cannot be both inside and outside a media
   query, and `light-dark()` would collapse it to one line at the price of the
   whole palette going invalid on a browser that lacks the function. The copies
   are kept honest by scripts/check-tokens.mjs, which fails the build if they
   ever drift apart — the trap is not the duplication, it is editing one of
   them and not the other. */
:root[data-theme="dark"] {
      --ink: #e6e8ed;
      --paper: #282c34;
      --surface: #323741;
      --surface-hi: #3c424e;
      --edge: #505866;
      --edge-strong: #929bab;
      --text-mute: #bec5d0;
      --text-faint: #abb4c2;
      --accent: #a5c7ef;
      --accent-fill: #a5c7ef;
      --accent-deep: #bed8f5;
      --on-accent: #202832;
      --accent-2: #a3d5cf;
      --signal: #c4b0e8;
      --fill-accent: #384658;
      --fill-person: #494151;
      --fill-info: #354b50;
      --w-bg: #282c34;
      --w-panel: #323741;
      --w-line: #929bab;
      --w-hair: rgba(230, 232, 237, 0.16);
      --w-mute: #bec5d0;
      --w-faint: #abb4c2;
      --ok: #b4d6ad;
      --warn: #e8cb99;
      --bad: #e6a5ab;

      --band: var(--surface-hi);
      --on-band: var(--ink);
      /* Deep here, and named rather than inherited, so the derived glass and
         hair above resolve against it. --paper is the dark theme's ground. */
      --nav-band: var(--paper);
      --on-nav-band: var(--ink);
      --bar-flood: var(--accent-fill);
      --bar-flood-label: var(--on-accent);
      --focus-flood-outer: var(--ink);
      --focus-flood-inner: var(--paper);
      /* Lifted rather than sunk: here the darkest thing on screen is the page. */
      --vs-dead: var(--surface);
      --vs-dead-ink: var(--text-mute);
}

/* Reduced motion collapses the durations; it does not delete the transitions.
   Gating each animation behind `no-preference` meant a visitor who asked for
   less motion got no state feedback at all — the underline, the focus weight
   and the status change all arrived with nothing to say they had changed. At
   1ms the signal still fires, it just does not travel. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-state: 1ms;
    --dur-field: 1ms;
  }
}

/* Scripts whose diacritics stack two high clip against the poster line-heights.
   Vietnamese is the worst case (ế, ự, ằ); Greek and Cyrillic are milder.
   Floor them per-language rather than flattening the ramp for everyone. */
:root:lang(vi),
:root:lang(el),
:root:lang(ru) {
  --d0-lh: 0.98;
  --d1-lh: 0.98;
  --d2-lh: 1;
}

/*!***************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[12].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[12].use[3]!./styles/poster.css ***!
  \***************************************************************************************************************************************************************************************************************************************************************/
/* EchoPage v2.0 "Kinetic Type" — the component layer.
   Structure lives here; type sizes come from Tailwind (text-d0 … text-d4),
   which reads the same tokens. Nothing in this file hardcodes a colour. */

/* A scrollbar you can see, on every screen.
 *
 * macOS hides scrollbars until something moves, which is fine on a page that
 * obviously continues and misleading on the console: a form ending in a section
 * heading with the fold cutting through it reads as the end of the form. The
 * report was literally "it is not clear that it scrolls".
 *
 * `scrollbar-gutter: stable` is the half that matters even where a scrollbar is
 * already drawn — it reserves the space at all times, so a page that grows past
 * one screenful no longer shifts its whole layout 15px sideways at the moment
 * it does. Global rather than scoped to the console, because a scrollbar that
 * appears on one screen and not the next is a stranger surprise than one that
 * is always there.
 *
 * The webkit block is what overrides the overlay behaviour; `scrollbar-color`
 * covers Firefox and newer Chromium, and neither names a value of its own. */
html {
  scrollbar-gutter: stable;
  scrollbar-color: var(--edge-strong) transparent;
}
::-webkit-scrollbar {
  inline-size: 12px;
  block-size: 12px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--edge-strong);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--ink);
  background-clip: padding-box;
}

/* ---- structure ---------------------------------------------------------- */

.ep-block {
  padding-block: clamp(46px, 8vw, 128px);
  padding-inline: var(--gut);
}

.ep-block-tight {
  padding-block: clamp(26px, 4vw, 56px);
}

/* Two adjacent floods can be photometrically identical — lime against yellow is
   1.01:1, yellow against mint 1.04:1 — so the boundary between two sections is
   invisible to anyone who does not separate those hues. The rule is the seam;
   colour is only ever the second carrier of it. */
.ep-block + .ep-block {
  border-block-start: var(--rule) solid var(--ink);
}

.ep-wrap {
  max-width: 1600px;
  margin-inline: auto;
  width: 100%;
}

.ep-narrow {
  max-width: 900px;
}

/* Section-flood colour: each section owns one token completely. This is the
   deliberate reversal of v1's "never flood a page with saturated colour" —
   here the flood carries structure rather than decorating it.

   Re-cut 2026-08-24 into the pastel family. Four of the six are fields with
   ink lettering; two are dark. Nothing in these rules names a value — that is
   why the ladder has now been re-pointed three times without a single call
   site being touched. */
.b-ink {
  background: var(--band);
  color: var(--on-band);
  --eye-pupil: var(--band);
}
.b-paper {
  background: var(--paper);
  color: var(--ink);
  --eye-pupil: var(--paper);
}
.b-white {
  background: var(--surface);
  color: var(--ink);
  --eye-pupil: var(--surface);
}
.b-lime {
  background: var(--fill-accent);
  color: var(--ink);
  --eye-pupil: var(--fill-accent);
}
.b-pink {
  background: var(--fill-person);
  color: var(--ink);
  --eye-pupil: var(--fill-person);
}

/* The hero. Barely a gradient by design — see the token. */
.b-hero {
  background-color: var(--paper);
  background-image: var(--grad-hero);
  color: var(--ink);
  --eye-pupil: var(--paper);
}

/* The site and dashboard headers, which used to be `.b-ink` and are no longer.
   They are the one flood that is not a section: it sits above every page, and in
   the light theme it carries its own warm ground rather than the deep band.

   Its own token rather than a re-pointed `--band`, because `--band` is shared by
   the ticker and three section floods — moving it would have repainted all of
   them to make one change.

   NO `background` HERE, deliberately. Both call sites are `.ep-nav .b-nav`, and
   `.ep-nav` declares the glass at equal specificity further down this file, so
   anything painted here loses. It used to paint anyway: the ground stayed deep,
   the colour below flipped to ink, and the light theme shipped ink lettering on
   a dark bar. The header's ground is `.ep-nav`'s to own — derived from the same
   `--nav-band` this rule reads for everything else, so there is one value and
   no way for the two to disagree again. */
.b-nav {
  color: var(--on-nav-band, var(--on-band));
  /* The eye counters take the SOLID band, not the glass: a pupil painted in a
     translucent colour shows the eyeball through itself. */
  --eye-pupil: var(--nav-band, var(--band));

  /* The focus pair follows the ground, not the element. `.b-ink` swaps it
     because the default ink-outside ring vanishes on a deep band — and the
     header was `.b-ink` until now, so dropping the swap outright would have
     made focus invisible in the dark theme, where this bar still falls back to
     `--band`. So the swap stays as the fallback and the light theme, whose
     header is now a pale ground, overrides it back to the ordinary pair. */
  --focus-outer: var(--nav-focus-outer, var(--focus-flood-outer));
  --focus-inner: var(--nav-focus-inner, var(--focus-flood-inner));
}

/* "You are here" in the console bar, and it has to be the INVERSE OF THE BAR
   rather than a named pair of colours.

   It was `bg-ep-paper text-ep-ink`, which is the inverse of a page, not of a
   header — and the header is the one flood that does not use --paper as its
   ground. Measured: on the cream bar the marker came out at 1.03:1 against it,
   and in the dark theme --nav-band IS --paper, so the marker was painting the
   bar's own colour onto the bar. The only thing separating the current
   destination from the other two was aria-current, which is real but is not
   visible.

   Reading --on-nav-band as the ground and --nav-band as the lettering makes the
   marker the exact reverse of whatever the bar happens to be, in any theme,
   with no second decision: 14:1 in the light theme, 17:1 in the dark, both ways
   round. */
.ep-nav-current {
  background: var(--on-nav-band, var(--on-band));
  color: var(--nav-band, var(--band));
}

/* The focus pair is ink-outside/paper-inside, which is invisible on the deep
   band. Swap it there so the ring keeps an edge on both sides wherever it
   lands. There used to be a second flood needing the same treatment; it was
   the loud one, and it is gone. */
.b-ink {
  --focus-outer: var(--focus-flood-outer);
  --focus-inner: var(--focus-flood-inner);
}

/* ---- the only two button shapes ----------------------------------------- */

.ep-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  /* Blue, not the light slab it was on the cream page. The rule that governs
     this button has always been "the action is the opposite of its ground", and
     on a cream page the opposite was ink. Every ground is dark now, so the
     opposite is no longer a value — it is the accent, and the accent is the
     one colour on this page that means "press me". An ink bar would still be
     the opposite of the ground, but ink is also every letter on the page, and
     an action must not look like a paragraph.
     Cream label on --accent-fill measures 7.04:1. */
  background: var(--accent-fill);
  color: var(--on-accent);
  border: 0;
  cursor: pointer;
  text-align: start;
  text-decoration: none;
  font-family: var(--ep-display);
  font-weight: 800;
  letter-spacing: -0.03em;
  font-size: clamp(20px, 3.6vw, 40px);
  line-height: 1;
  padding: clamp(14px, 2.4vw, 24px) clamp(16px, 2.6vw, 28px);
}
/* The quiet twin: same shape, no accent. This is the "not now" of a pair —
   the consent strip's refuse bar, the secondary route out of an error. */
.ep-bar-paper {
  background: var(--surface-hi);
  color: var(--ink);
  box-shadow: inset 0 0 0 var(--rule) var(--edge-strong);
}
/* The third tone, and the only one that exists because of a collision.
 *
 * `.ep-bar-paper` is a near-white panel inside a 2px strong edge. At poster
 * scale that is unmistakable; at form scale, stacked among fields that are also
 * a pale panel inside a 2px edge, it becomes a fourth input box — and the one
 * on the sign-in screen says "No account yet? Create one", which is the single
 * control a visitor without an account needs to find. It was hiding among the
 * things it is not.
 *
 * So: the accent at tint strength. Same hue as the submit below it, a quarter
 * of the weight — the quiet sibling of the action rather than a rival to it, and
 * the only tinted ground on the screen, so nothing else can be mistaken for it.
 * Ink on the tint measures 8.66:1 in the light theme and 12.4:1 in the dark.
 *
 * Both themes come free: `--fill-accent` is re-pointed per theme, so this rule
 * names no value and needs no override. */
.ep-bar-tint {
  background: var(--fill-accent);
  color: var(--ink);
  box-shadow: inset 0 0 0 var(--rule) var(--accent-fill);
}

/* The bar at dialog scale.
 *
 * The poster bar is sized for a hero — clamp(20px, 3.6vw, 40px), text-align:
 * start, the label and its arrow pushed to opposite ends. Inside a dialog that
 * is too loud, and the start-alignment is actively wrong when two bars are a
 * question and its opposite: whichever label is shorter reads as the lighter
 * answer.
 *
 * So this centres, shrinks, and — the part that matters — takes full height, so
 * a pair in a grid row stays identical even when one translation wraps to two
 * lines and the other does not. Equal weight cannot be achieved by choosing
 * equal-length words; there are thirteen languages and the words are not ours to
 * choose. It has to come from the layout. */
.ep-bar-choice {
  justify-content: center;
  text-align: center;
  height: 100%;
  /* Both clamps bottom out together on a phone: 15px of text on line-height 1
     inside 12px of padding is a 39px control, and this is the shape that asks a
     visitor to refuse tracking. The floor is stated here rather than at the call
     site so a new pair of choice bars cannot be born 5px short; past roughly
     860px the two clamps clear 44px between them and this line does nothing. */
  min-height: 44px;
  font-size: clamp(15px, 1.9vw, 22px);
  letter-spacing: -0.02em;
  padding: clamp(12px, 1.6vw, 18px) clamp(14px, 1.8vw, 20px);
}

/* The bar at form scale.
 *
 * Between the poster bar and the choice pair. An auth card is 448px wide, and a
 * bar sized for a hero — 40px of display type in 24px of padding — fills a third
 * of it before a single field is drawn, which makes the screen read as a poster
 * with a form stuck underneath rather than as a form.
 *
 * It shrinks and it stays START-ALIGNED, which is the difference from
 * `.ep-bar-choice`. That one centres because it is half of a question-and-its-
 * opposite pair, where a centred label is the only way two different-length
 * translations carry equal weight. These bars are stacked and sequential — sign
 * in, or go and make an account — so the label keeps the reading edge and the
 * arrow keeps the far one.
 *
 * 44px minimum for the same reason `.ep-bar-choice` states it: the clamps only
 * clear it on their own past roughly 860px, and this control lives on a 448px
 * card. */
.ep-bar-form {
  min-height: 44px;
  font-size: clamp(16px, 2vw, 20px);
  letter-spacing: -0.02em;
  padding: clamp(11px, 1.4vw, 14px) clamp(14px, 1.8vw, 18px);
}

/* On the deep band the accent bar has almost no edge — it is dark on dark.
   Inverting keeps one action fill by keeping one RELATIONSHIP: the bar is
   always the opposite of its ground. */
.b-ink .ep-bar {
  background: var(--bar-flood);
  color: var(--bar-flood-label);
}

.ep-bar .arw {
  font-family: var(--ep-ui);
  font-weight: 700;
  font-size: 0.7em;
  flex: none;
}

/* The second shape: a word with a rule under it. */
.ep-word {
  font-family: var(--ep-display);
  font-weight: 800;
  letter-spacing: -0.03em;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 0.07em;
  color: inherit;
}
.ep-link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.22em;
}

/* Standalone-target geometry for the two word shapes.
 *
 * WHICH ONE: reach for `.ep-word-btn` on a `.ep-word` and `.ep-link-btn` on a
 * `.ep-link` — the names carry the intent at the call site, the box is defined
 * once here because it is the same box. Neither belongs on a link sitting INSIDE
 * a sentence: SC 2.5.8 exempts those, and stretching one splits the paragraph it
 * is set in. They are for the link or button that stands alone in its own <p>,
 * <li> or flex row, where a fingertip has nothing else to aim at. For a
 * locale-aware link use the `WordLink` component, which is these classes plus
 * the size step.
 *
 * The padding grows the hit box and the equal negative margin hands the growth
 * straight back to the flow, so the target reaches 44px while the drawn glyph
 * keeps its size AND the line rhythm around it is unchanged to the pixel. */
.ep-word-btn,
.ep-link-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: 12px;
  margin-block: -12px;
}

/* ---- text ---------------------------------------------------------------- */

.ep-eyebrow {
  font-family: var(--ep-ui);
  font-size: 12px;
  letter-spacing: 0.24em;
  font-weight: 600;
  text-transform: none;
}

.ep-lead {
  font-size: var(--lead-size);
  line-height: var(--lead-lh);
  max-width: 34ch;
  font-weight: 500;
}

.ep-display {
  font-family: var(--ep-display);
  text-wrap: balance;
  overflow-wrap: break-word;
}

.ep-num {
  font-family: var(--ep-display);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.045em;
  line-height: 0.82;
  font-weight: 800;
}

.ep-mute {
  opacity: 0.72;
}

.ep-mark {
  background: var(--fill-accent);
  color: var(--ink);
  padding-inline: 0.12em;
}

.ep-rule {
  border: 0;
  border-block-start: var(--rule) solid currentColor;
  margin-block: clamp(18px, 3vw, 34px);
  opacity: 1;
}
.ep-rule-thin {
  border-block-start-width: 1px;
  opacity: 0.35;
}

/* ---- chips (services, skills, locales) ----------------------------------- */

.ep-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.ep-chip {
  border: var(--rule) solid currentColor;
  padding: 7px 14px;
  font-size: var(--w-small-size);
  font-weight: 600;
  line-height: 1.2;
}

/* ---- work register ------------------------------------------------------- */

.ep-panel {
  background: var(--w-panel);
  border: var(--rule) solid var(--w-line);
  border-radius: var(--r-panel);
  padding: clamp(14px, 2vw, 22px);
}

/* ---- the panel, poster register ------------------------------------------
   The marketing pages had no container at all, and that was the whole of the
   "everything merges" fault: six full-bleed fields of the same pale ground,
   separated by one 2px seam, read as a single column of prose no matter how the
   type inside them is set. A section flood says WHERE you are; a panel says
   THIS IS ONE THING, and the page needs both.

   Separation is the BORDER's job. --white on --paper measures 1.09:1, so the
   fill is doing nothing a reader could rely on — it is there to keep the type
   inside off the cream and to let the border read as an edge rather than as an
   underline. Anything that needs the box to be findable has to survive the fill
   being invisible, and here it does.

   Fill and text colour are both stated rather than inherited, so this box is the
   same box on every flood it is dropped onto. Inheriting `currentColor` for the
   border would have made it a white box with a white border on --purple.

   NO PANEL INSIDE A PANEL. One level. A picture, a list or a heading goes in;
   another bordered box does not. */
.ep-panel-poster {
  background: var(--surface);
  color: var(--ink);
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  padding: clamp(18px, 2.6vw, 30px);
  /* flow-root, so a first child's margin-block-start collapses inside the box
     instead of pushing the whole panel down the grid row it shares. */
  display: flow-root;
}

/* A question, rather than a panel that happens to hold one.
   
   --fill-info and not a green picked by eye: the fill tokens are named for the
   JOB and not the hue, they are the three colours whole blocks are already
   flooded with, and ink is measured against each of them — so a question box
   lands inside the system instead of beside it. It follows the theme on its
   own, which a literal hex would not: the same token is a muted green on paper
   and a deep teal in the dark, where a light green would leave light ink on a
   light ground.

   Only the ground changes. The rule, the radius and the padding stay the
   poster panel's, so an opened question is the same object as a closed one and
   the FAQ does not become a second panel vocabulary. */
.ep-panel-question {
  background: var(--fill-info);
}

/* ---- the without/with list ----------------------------------------------
   The same square vocabulary as .ep-state, minus the state colours: hollow for
   the column about the reader's week as it stands, filled for the column about
   the page. Shape carries it, exactly as it does for live/draft, so it survives
   greyscale, forced-colors and a deuteranope — and neither column is tinted,
   because in this palette a colour means a state of the product and "without"
   is not one.

   --w-small-size rather than body size is a measure decision, not a whisper:
   these items are written to hold ONE LINE at 390px, where the panel's inner
   width is about 302px after the mark, and 14px is what makes ~30 characters
   fit there. The rule for the copy is to cut words, never to shrink this. */
.ep-items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
.ep-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-family: var(--ep-ui);
  font-size: var(--w-small-size);
  line-height: 1.35;
  font-weight: 700;
}
.ep-item::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  border: 2px solid currentColor;
  flex: none;
  /* Aligns the square to the cap height of the first line rather than to the
     line box, which sits it a couple of pixels high next to 14px type. */
  margin-block-start: 0.25em;
}
.ep-item[data-mark="filled"]::before {
  background: currentColor;
}

/* ---- the assistant names inside an example ------------------------------
   Type, not logos. Set in the display face at weight, separated by the same
   leading rule the ticker uses, so the row reads as a deliberate typographic
   treatment and not as three images that failed to load — and so nothing here
   restyles a mark we have no licence to restyle. Names are data, never
   messages: a transliterated trademark is both wrong and no longer the word the
   reader recognises. */
.ep-assistants {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
  row-gap: 6px;
}
.ep-assistants > li {
  font-family: var(--ep-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: clamp(15px, 1.9vw, 20px);
  line-height: 1.2;
  padding-inline: clamp(10px, 1.4vw, 16px);
  border-inline-start: var(--rule) solid currentColor;
  white-space: nowrap;
}
.ep-assistants > li:first-child {
  padding-inline-start: 0;
  border-inline-start: 0;
}
.ep-label {
  font-size: var(--w-label-size);
  letter-spacing: var(--w-label-track);
  font-weight: 700;
  color: var(--w-faint);
  text-transform: uppercase;
}
/* A poster eyebrow is not a field name. .ep-label is 10.5px uppercase at 0.2em,
   which is a graphic device; read as the name of the box you are about to type
   your own address into it is small, shouted and hard to scan. Form labels get
   their own class at reading size in sentence case. */
.ep-field-label {
  font-size: var(--w-small-size);
  font-weight: 700;
  color: var(--w-faint);
  letter-spacing: normal;
  text-transform: none;
}
/* The box itself, lifted out of four page files that each carried the same
   Tailwind string. It moved here the day it needed an invalid state: a rule
   that lives in one place can grow one, and four copies of a class list grow
   three-quarters of one. */
.ep-field {
  display: block;
  inline-size: 100%;
  margin-block-start: 6px;
  border: var(--rule) solid var(--w-line);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--ep-ui);
  font-size: var(--wh3-size);
  line-height: 1.3;
  padding-block: 10px;
  padding-inline: 12px;
}

/* A box with a control living inside it — today that is the password reveal.
 *
 * The wrapper takes the field's own top margin and the field gives it up, so
 * adding a toggle does not move the box a reader was already looking at. */
.ep-field-wrap {
  position: relative;
  display: block;
  margin-block-start: 6px;
}
.ep-field-wrap > .ep-field {
  margin-block-start: 0;
  /* Room for the button, and no more. Sized against the longest of the
     twenty-six labels — German's "Verbergen" — RENDERED and measured rather
     than counted in characters: at the button's own size it is 73px, where 9ch
     of the field's 18px face came out at 102px and stole 29px of the password
     from every reader of every language to fit a word only Germans see.

     Expressed as a multiple of the button's font size, not as pixels, so it
     still follows a reader who has scaled their text up. 12px of padding on
     each side of the word is the 24px. */
  padding-inline-end: calc(5.3 * var(--w-small-size) + 24px);
}

/* Show / hide, as a word rather than an eye.
 *
 * An eye is the usual choice and it is ambiguous in the one way that matters:
 * it cannot say whether it is REPORTING that the password is visible or
 * OFFERING to make it visible, and half of every audience reads it the wrong
 * way round. A word can only mean one thing, and it changes to the other word
 * when pressed, so what a screen reader announces is the state that now exists.
 *
 * §6 allows two button shapes and this spends neither: it is type set in the
 * link idiom, inside the field it belongs to. 44px of target comes from the
 * field's own height rather than from padding that would push the box taller. */
.ep-field-reveal {
  position: absolute;
  inset-inline-end: 0;
  inset-block: 0;
  display: inline-flex;
  align-items: center;
  padding-inline: 12px;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--w-mute);
  font-family: var(--ep-ui);
  font-size: var(--w-small-size);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.ep-field-reveal:hover {
  color: var(--ink);
}

/* Some boxes are disabled directly rather than by an enclosing fieldset, so
   the fade cannot live only on `fieldset:disabled`. */
.ep-field:disabled {
  opacity: 0.6;
}

/* The refused box. Colour is the LAST carrier here as everywhere else: the
   border also doubles in weight, so the field reads as wrong on a monochrome
   screen and under forced colours, and the sentence underneath says what is
   wrong in words. Keyed off aria-invalid rather than a class, so the visual
   state and the state a screen reader announces cannot come apart — there is
   only one thing to set. */
.ep-field[aria-invalid="true"] {
  border-color: var(--bad);
  border-width: calc(var(--rule) * 2);
}

/* The sentence under the box that names what went wrong.
 *
 * UNDER THE FIELD, always. It used to be one block below the submit button
 * listing everything at once, which is the arrangement that makes somebody
 * scroll past the thing they must fix to read that something must be fixed.
 * Anchored here it is in the same glance as the box, and aria-describedby means
 * a screen reader reads it as part of the field rather than as loose prose at
 * the end of the form.
 *
 * Same square as `.ep-state[data-state="failed"]` — thick on every side, in
 * --bad — because this IS that state, wearing a form's clothes. Reusing the
 * glyph is what keeps "something is wrong" one visual idea across the product
 * rather than two that happen to both be red. */
.ep-field-error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-block-start: 6px;
  color: var(--bad);
  font-size: var(--w-small-size);
  font-weight: 700;
  line-height: 1.4;
}
.ep-field-error::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  border: 5px solid currentColor;
  flex: none;
  /* Nudged down to sit on the first line's cap height rather than its box top,
     so the square lines up with the letters on a one-line message and stays put
     when the message wraps to three. */
  margin-block-start: 3px;
}

/* The quiet line under a box that says what will be accepted, BEFORE anything
   is refused. It is not a state, so it has no glyph and no state colour. */
.ep-field-hint {
  margin-block-start: 6px;
  color: var(--w-faint);
  font-size: var(--w-small-size);
  line-height: 1.4;
}

.ep-status {
  font-size: var(--w-label-size);
  letter-spacing: var(--w-label-track);
  font-weight: 700;
  text-transform: uppercase;
}

/* The unconfirmed-address strip, under the console header.
 *
 * Red, and not ONLY red: it is a filled band with a heavier weight on its first
 * clause and a control inside it, so it survives a monochrome screen and forced
 * colours the same way `.ep-state` does. --bad as the ground rather than as the
 * lettering, because a coloured sentence in a page full of sentences is a
 * sentence, and this has to be the thing the eye lands on when the console
 * opens.
 *
 * Full-bleed inside the header's own gutters and directly under the bar, so it
 * reads as part of the chrome — it is true on every console screen, not a
 * remark the editor is making.
 *
 * role="status" and not "alert": the address has been unconfirmed since before
 * this page loaded, so it is a standing condition rather than something that
 * just happened to the person reading. Assertive would interrupt whatever a
 * screen-reader user was doing to tell them something that has been true for
 * days. */
.ep-unverified {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  background: var(--bad);
  color: var(--surface-hi);
  padding: 10px var(--gut);
  font-size: var(--w-small-size);
  line-height: 1.4;
}
.ep-unverified-text {
  margin: 0;
  min-width: 0;
  flex: 1 1 20rem;
}
.ep-unverified-title {
  font-weight: 800;
}
/* The action is a word on the band, not a second button shape — §6 allows two
   and this strip is not the place to spend one. The underline is what makes it
   a control rather than emphasis, and 44px of target comes from padding with an
   equal negative margin, so the strip does not grow a row to hold it. */
.ep-unverified-action {
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  font-weight: 800;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  min-height: 44px;
  padding-block: 12px;
  margin-block: -12px;
  flex: none;
}
.ep-unverified-done {
  margin: 0;
  font-weight: 800;
  flex: none;
}

/* ---- state: shape AND word, never colour alone ---------------------------
   Every state renders a localised word next to a square glyph, and the square
   differs by fill pattern rather than by hue — filled, hollow, half, crossed,
   barred. Colour is the third and most redundant carrier, so the state survives
   a monochrome screen, a colour-blind reader and a printed page. */
.ep-state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* Deliberately NOT the `font` shorthand: it resets font-family, so an
     .ep-state landing on an element that also carries .ep-display silently
     replaced Archivo with the UI face. Set only what this needs and inherit
     the rest. */
  font-size: var(--w-small-size);
  font-weight: 700;
  min-height: 44px;
}

/* The square is the redundant carrier, so the five states have to differ by
   SHAPE and not only by hue — a greyscale print, a forced-colors mode and a
   deuteranope all have to be able to tell them apart. Border geometry does that
   with solid fills only; a gradient would read as one here and the style forbids
   them outright. Logical border properties so the working state's thick edge
   leads in Arabic and Hebrew too. */
.ep-state::before {
  content: "";
  inline-size: 12px;
  block-size: 12px;
  border: 2px solid currentColor;
  flex: none;
}
.ep-state[data-state="live"] {
  color: var(--ok);
}
.ep-state[data-state="live"]::before {
  background: currentColor; /* solid */
}
.ep-state[data-state="draft"] {
  color: var(--w-faint);
}
.ep-state[data-state="draft"]::before {
  background: none; /* thin outline, empty */
}
.ep-state[data-state="working"] {
  color: var(--warn);
}
.ep-state[data-state="working"]::before {
  border-inline-start-width: 7px; /* thick leading edge */
}
.ep-state[data-state="failed"] {
  color: var(--bad);
}
.ep-state[data-state="failed"]::before {
  border-width: 5px; /* thick on every side */
}
.ep-state[data-state="down"] {
  color: var(--ink);
}
.ep-state[data-state="down"]::before {
  border-block-width: 5px; /* barred: thick top and bottom, thin sides */
}
/* Arabic and Hebrew have no letter case and no tradition of letterspacing for
   emphasis; applying either turns a word into damage rather than a style. */
:lang(ar) .ep-state,
:lang(he) .ep-state {
  letter-spacing: normal;
  text-transform: none;
}

/* ---- grids. Always minmax(0,1fr), never a bare 1fr: a bare 1fr is
   minmax(auto,1fr) and resolves to min-content, which silently clips a <pre>
   or a table inside an overflow:clip parent at 375px. ---------------------- */

.ep-g2,
.ep-g3,
.ep-g4 {
  display: grid;
  gap: clamp(16px, 2.4vw, 32px);
}
/* Mobile first, and the direction is the whole point rather than a preference.
   These were written the other way round — the unprefixed rule was the 2, 3 and
   4 column desktop grid, and two `max-width` blocks took columns away again at
   900px and 620px. Read literally that says the phone is the desktop with parts
   removed, and it behaves that way too: a new grid added to this file is a
   multi-column desktop grid on a 375px screen until somebody remembers to widen
   the override list.
   
   One column is now the rule, stated once, and `min-width` adds columns as there
   is room for them. A new grid is correct on a phone by default and has to be
   given permission to be anything else. */
.ep-g2,
.ep-g3,
.ep-g4 {
  grid-template-columns: minmax(0, 1fr);
}

/* 620px: the point where two columns of body text stop being cramped. */
@media (min-width: 620px) {
  .ep-g2,
  .ep-g3,
  .ep-g4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* 900px: room for the counts the class names actually promise. */
@media (min-width: 900px) {
  .ep-g3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .ep-g4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* Anything wide scrolls inside its own box; the document never does.
   max-width and min-width are both load-bearing: without them a table carrying
   its own min-width propagates that width up to the documentElement's scrollable
   overflow, so the box scrolls correctly AND the page scrolls sideways behind it. */
.ep-scroller {
  overflow-x: auto;
  max-width: 100%;
  min-width: 0;
  /* contain:paint is the load-bearing line. Without it a <tbody> inside a
     border-collapse table still contributes its full width to the VIEWPORT's
     scrollable overflow even though this box clips it visually: the table
     scrolls correctly in its own box and the whole page scrolls sideways behind
     it. Measured on the pricing table at 375px — 576px of document against a
     375px viewport, with every ancestor already 375 or narrower. */
  contain: paint;
  -webkit-overflow-scrolling: touch;
}

.ep-mono {
  font-family: var(--ep-mono);
  font-size: 13px;
  line-height: 1.6;
}

/* Logical inset utilities Tailwind 3 does not ship. The picker is anchored to the
   end of its trigger, which must follow writing direction rather than "right". */
.inset-inline-0 {
  inset-inline: 0;
}
.inset-inline-end-0 {
  inset-inline-end: 0;
}

/* ---- "by ORKCOM" ---------------------------------------------------------
   Same convention as dither-ork and cogitorium: the mark spells ORK, the type
   finishes the word. The mark is alpha-only and masked, so it carries no colour
   of its own and belongs to whatever flood it sits in. */
.by-ork {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: inherit;
  text-decoration: none;
  opacity: 0.72;
}
.by-ork:hover {
  opacity: 1;
}
.by-word {
  font-family: var(--ep-ui);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
}
/* The mark and the two letters that finish the name are one object: they scale,
   dim and hover together and must never drift apart by a pixel. */
.ork-lockup {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.ork-mark {
  display: block;
  width: 42px;
  height: 21px;
  background-color: currentColor;
  mask-repeat: no-repeat;
  mask-position: center;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  -webkit-mask-size: contain;
}
.ork-com {
  font-family: var(--ep-display);
  font-weight: 800;
  font-size: 17px;
  letter-spacing: -0.02em;
  line-height: 1;
}

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

/* ---- site header ---------------------------------------------------------
   The header carries its own flood rather than inheriting the section under it.
   Laid on the purple hero it was the same field as the hero, so the links had
   nothing to sit against and read as text floating on the poster. An ink band
   gives them a ground and separates the chrome from the argument. */
.ep-nav-item {
  position: relative;
  text-decoration: none;
}
.ep-nav-item::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 2px;
  height: 2px;
  background: var(--accent-fill);
  transform: scaleX(0);
  transform-origin: inline-start;
  transition: transform var(--dur-state) var(--ease-out);
}
.ep-nav-item:hover::after,
.ep-nav-item:focus-visible::after,
.ep-nav-item[aria-current]::after {
  transform: scaleX(1);
}

/* ---- two lenses, one field ----------------------------------------------
   The product's core claim is that the human page and the machine artifact are
   the SAME page seen twice. Stacked as two bands you had to scroll to compare
   them; side by side the seam does the arguing. */
.ep-lens-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}
.ep-lens-half {
  padding-block: clamp(46px, 7vw, 110px);
  padding-inline: clamp(20px, 3.2vw, 56px);
  min-width: 0;
}
.ep-lens-inner {
  max-width: 760px;
  margin-inline: auto;
  width: 100%;
}
/* Two columns of poster type do not fit a phone, so one column is the rule and
   the split is what gets added — the same inversion as the grids above. Stated
   this way the phone is not a special case that somebody has to remember. */
@media (min-width: 900px) {
  .ep-lens-split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---- the rank line -------------------------------------------------------
   A flat bordered strip, drawn with a border and nothing else. There is no
   radius token in this system and no shadow, which rules out a badge, a pill
   and a ribbon by construction — the strip is what this language has instead,
   and it is the same 2px rule that draws every other edge on the page.

   It sits above the headline and carries no target, so 44px does not apply and
   the box stays as tight as the type.

   Tracking is 0.12em rather than the eyebrow's 0.24em because this string is
   translated into thirteen languages, several of which run about 30% longer
   than English; the wider tracking pushed the German and Finnish forms onto a
   third line at 390px. It wraps rather than scrolls, so a long translation
   costs a line and never costs the layout. */
.ep-rank {
  display: inline-block;
  max-width: 100%;
  border: var(--rule) solid currentColor;
  padding: 8px 12px;
  font-family: var(--ep-ui);
  font-size: 12px;
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: 0.12em;
  margin-block-end: clamp(18px, 3vw, 28px);
}
/* Same reasoning as .ep-state: neither script letterspaces for emphasis, and
   applying it there damages the word rather than styling it. */
:lang(ar) .ep-rank,
:lang(he) .ep-rank {
  letter-spacing: normal;
}

/* ---- the hero action: one field, one button ------------------------------
   The row is a paper plate laid on the purple flood, not an outlined shape cut
   into it. That is a contrast decision, not a taste one: SC 1.4.11 wants 3:1
   for the boundary of a control, and ink on --purple measures 2.05:1, so an ink
   outline around a transparent field would have had no findable edge. Paper on
   --purple is 8.81:1 and the ink rule then draws the detail on top of it.

   Column first. The two-column row is what gets added when there is width for
   it, so the phone is the rule rather than the desktop with parts removed. */
.ep-import-label {
  display: block;
  font-family: var(--ep-ui);
  font-size: var(--w-body-size);
  line-height: var(--w-body-lh);
  font-weight: 600;
  margin-block-end: 10px;
}

.ep-import-row {
  display: flex;
  flex-direction: column;
  border: var(--rule) solid var(--ink);
  background: var(--paper);
  max-width: 760px;
  /* The system's one radius, and this plate had been missing it. `overflow:
     hidden` rather than a radius on the button as well: the submit sits flush
     against the border on two sides, and rounding it separately would leave a
     hairline of plate showing through the corner. Clipping the parent makes the
     two behave as one object, which is what they look like. */
  border-radius: var(--r-panel);
  overflow: hidden;
}

.ep-import-field {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--ep-ui);
  /* 18px. Anything at or under 16px lets iOS Safari zoom the page when the
     field takes focus, which on a hero drags the headline off screen at the
     moment the visitor commits to typing. */
  font-size: var(--wh3-size);
  line-height: 1.3;
  min-height: 52px;
  padding: 12px 14px;
}
.ep-import-field::-moz-placeholder {
  color: var(--w-faint);
}
.ep-import-field::placeholder {
  color: var(--w-faint);
}

/* The seam between field and button is the ink fill itself, so there is no
   separate divider rule: a 2px ink border drawn on an ink ground is invisible,
   and adding one would only be a line in this file that renders as nothing. */
.ep-import-go {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: none;
  background: var(--ink);
  color: var(--paper);
  border: 0;
  cursor: pointer;
  text-align: start;
  font-family: var(--ep-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: clamp(18px, 2.6vw, 26px);
  line-height: 1;
  min-height: 52px;
  padding: 14px 16px;
}
.ep-import-go .arw {
  font-family: var(--ep-ui);
  font-weight: 700;
  font-size: 0.7em;
  flex: none;
}

/* 560px is where the label, a usable measure of address and the button label
   stop competing for the same line. */
@media (min-width: 560px) {
  .ep-import-row {
    flex-direction: row;
    align-items: stretch;
  }
  .ep-import-go {
    justify-content: center;
    text-align: center;
  }
}

/* The error is a flooded strip rather than red type, because on --purple the
   --bad token measures 1.6:1 and is unreadable; ink flooded under paper type is
   18.4:1 and works on every flood this row could ever be dropped onto. */
.ep-import-error {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--ep-ui);
  font-size: var(--w-small-size);
  font-weight: 700;
  line-height: 1.4;
  padding: 8px 12px;
  margin-block-start: 10px;
  max-width: 760px;
}

/* ---- the assistant strip -------------------------------------------------
   A full-bleed ink seam under the hero. It moves by itself and runs well past
   five seconds, so WCAG 2.2.2 applies and the three things it asks for are all
   here rather than assumed:

     1. the names are real text, in reading order, in the DOM — the movement is
        decoration laid over content that is already readable without it;
     2. a visible pause control, at the 44px standalone-target size;
     3. reduced motion stops the lap entirely and wraps the same names into a
        static row, so "reduced" still means every name is readable.

   The duplicate lane is aria-hidden, so a screen reader hears thirteen names
   once and not twenty-six. */
.ep-ticker {
  padding-block: clamp(18px, 3vw, 30px);
  /* --purple against --ink is a colour change of about 2.4:1 in luminance,
     which is the same failure the .ep-block seam rule exists to fix: two
     adjacent floods that only some eyes separate. The paper rule is the seam. */
  border-block-start: var(--rule) solid var(--paper);
  overflow: clip;
}

.ep-ticker-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  max-width: 1600px;
  margin-inline: auto;
  padding-inline: var(--gut);
}


.ep-ticker-view {
  overflow: clip;
  margin-block-start: clamp(12px, 2vw, 20px);
}

.ep-ticker-lane {
  display: flex;
  width: -moz-max-content;
  width: max-content;
  animation: ep-ticker-run var(--dur-ticker) linear infinite;
}
/* Pausing stops the lap where it stands instead of returning it to the start:
   a control that jumps the content back to the beginning is a reset, and a
   visitor presses this because they want to read the name in front of them. */
.ep-ticker-lane[data-paused="true"] {
  animation-play-state: paused;
}

.ep-ticker-list {
  display: flex;
  flex: none;
  list-style: none;
  margin: 0;
  padding: 0;
}
.ep-ticker-list > li {
  font-family: var(--ep-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: clamp(20px, 3.6vw, 40px);
  line-height: 1.2;
  padding-inline: clamp(14px, 2.4vw, 28px);
  border-inline-start: var(--rule) solid currentColor;
  white-space: nowrap;
}

@keyframes ep-ticker-run {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
/* The two lanes are identical, so -50% is exactly one lane width and the loop
   is seamless. In a right-to-left document the flex row starts at the right
   edge and the duplicate sits to the LEFT of the original, so the lane has to
   travel the other way or it scrolls into empty space. */
[dir="rtl"] .ep-ticker-lane {
  animation-name: ep-ticker-run-rtl;
}
@keyframes ep-ticker-run-rtl {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ep-ticker-view {
    overflow: visible;
    /* Full bleed is a property of the MOVING strip — names have to enter and
       leave at the viewport edge for the lap to read as continuous. A static
       row that starts hard against the edge just looks cropped, so the gutter
       comes back the moment the movement goes. */
    padding-inline: var(--gut);
  }
  .ep-ticker-lane {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    row-gap: 8px;
  }
  /* flex:none is what makes the moving lane keep its full max-content width;
     left in place here the list simply never reaches the edge it would have to
     wrap at, and thirteen names run off the side of a strip that is no longer
     moving them back. Shrinking is what turns the lap into a paragraph. */
  .ep-ticker-list {
    flex: 0 1 auto;
    min-width: 0;
    flex-wrap: wrap;
    row-gap: 8px;
  }
  /* Two copies of every name wrapped into a static row is a stutter, not a
     loop, so the decorative lane goes and the readable one stays. */
  .ep-ticker-list[aria-hidden="true"] {
    display: none;
  }
}



/* ── the header ───────────────────────────────────────────────────────────────
   Sticky, so its height is spent from EVERY viewport for the whole session.
   Measured before this rule: the two-row header was 120px of a 375x812 phone
   (15%) and the consent strip another 238px (29%) — 44% of the first screen was
   chrome. That is why the links moved behind a disclosure rather than why the
   glass was added: a sticky bar has to be cheap.

   0.75 and not less. Paper text rides over whatever scrolls beneath, so the
   worst case is the lightest ground. Measured, paper #fbf5e7 over ink at 0.75:
   8.41:1 on white, 8.74 on paper, 10.23 on lime, 16.26 on purple. The bare
   minimum for 4.5:1 over pure white is 0.583; the extra buys headroom for a
   lighter field being introduced later, which a fixed alpha cannot adapt to.

   `sticky`, never `fixed`: it stays in flow, so no sibling needs a compensating
   pad and nothing is occluded on first paint. No shrink-on-scroll, no
   hide-on-scroll — "always visible" was the brief, and movement driven by
   scroll position is the defect already removed from the headlines. */
.ep-nav {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background: var(--nav-glass);
  backdrop-filter: blur(14px) saturate(1.15);
  border-block-end: var(--rule) solid var(--nav-hair);
}

/* Without the blur the translucency reads as a mistake rather than as glass, so
   where it is unsupported the bar goes fully solid instead of half-way. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ep-nav {
    background: var(--band);
  }
}

/* A real user setting for people who find translucent chrome hard to parse, not
   decoration to honour when convenient. */
@media (prefers-reduced-transparency: reduce) {
  .ep-nav {
    background: var(--band);
    backdrop-filter: none;
  }
}

@media (forced-colors: active) {
  .ep-nav {
    background: Canvas;
    border-block-end: 1px solid CanvasText;
    backdrop-filter: none;
  }
}

/* The phone menu. A native <details>, because SiteNav is deliberately not a
   client component — it is rendered from client modules too, and a client
   component cannot render an async server one. <details> gives the disclosure,
   the keyboard and the Escape key with no state and no JavaScript at all. */
.ep-nav-menu > summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-block-size: 44px;
  min-inline-size: 44px;
  padding-inline: 12px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.ep-nav-menu > summary::-webkit-details-marker {
  display: none;
}
.ep-nav-menu > summary::after {
  content: "";
  inline-size: 8px;
  block-size: 8px;
  border-inline-end: 2px solid currentColor;
  border-block-end: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}
.ep-nav-menu[open] > summary::after {
  transform: translateY(2px) rotate(-135deg);
}
/* Full-bleed under the bar rather than a floating panel: the header has no
   radius and no shadow to hang one from, and a phone has no room for a popover
   that is narrower than the screen. */
.ep-nav-menu[open] > .ep-nav-menu-body {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  display: grid;
  gap: 4px;
  padding: 12px var(--gut) 16px;
  background: var(--band);
  border-block-start: var(--rule) solid var(--nav-hair);
}

/* ── the stacked plan cards on /pricing ───────────────────────────────────────
   Under 768px the four-column ladder becomes one card per plan. Before this
   they were sections divided by a --w-hair rule — the SAME rule that divides
   every row inside a plan — so on a phone the boundary between two plans was
   indistinguishable from the boundary between two rows and a reader could not
   tell where one plan ended. A filled header band fixes that: the eye lands on
   it before it starts reading values.

   The four bands are floods this page already uses, stepping light to dark as
   the plan gets bigger, so the ramp says which way is up before a number is
   read. NOT --mint, --pink or --yellow: those carry live, person and working in
   the console, and a plan tier is none of the three. */
.ep-plan-card {
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  overflow: hidden;
  background: var(--surface);
}
.ep-plan-card-head {
  padding: 12px clamp(14px, 3vw, 20px);
  border-block-end: var(--rule) solid var(--ink);
}
.ep-plan-card-body {
  padding: clamp(10px, 2.4vw, 16px) clamp(14px, 3vw, 20px)
    clamp(14px, 3vw, 20px);
}
.ep-plan-card[data-tier="paper"] .ep-plan-card-head {
  background: var(--paper);
  color: var(--ink);
}
.ep-plan-card[data-tier="lime"] .ep-plan-card-head {
  background: var(--fill-accent);
  color: var(--ink);
}
.ep-plan-card[data-tier="accent"] .ep-plan-card-head {
  background: var(--accent-fill);
  color: var(--on-accent);
}
.ep-plan-card[data-tier="ink"] .ep-plan-card-head {
  background: var(--band);
  color: var(--on-band);
}

/* ---- the editor ---------------------------------------------------------
   The profile editor is one long form and it did not look like one. Four
   sections separated by 40px of nothing, no rule anywhere, so the boundary
   between "Who you are" and "What you do" was the same as the boundary between
   two fields inside either — and the first section is 696px against 160 for the
   next, so the eye had no way to tell a long section from two short ones run
   together. Measured on the running page before the change. */

/* The title stays. It is the one line that says what the whole screen is for,
   and it used to scroll away in the first flick, leaving a column of fields
   with no name on it.

   `--ep-console-nav` is written by DashboardShell from a ResizeObserver, not
   hardcoded — the bar above is one row, two, or three depending on whether the
   profile is published and whether the address is confirmed, and it wraps in
   some languages. A constant would be wrong in most of those states, and wrong
   here means this strip floats in a gap or hides under the bar. The fallback is
   0px so the strip still sticks to the top of the viewport if the variable is
   ever missing, which is the harmless failure of the two. */
.ep-editor-head {
  position: sticky;
  inset-block-start: var(--ep-console-nav, 0px);
  z-index: 20;
  background: var(--w-panel);
  border-block-end: var(--rule) solid var(--w-line);
  padding-block: 10px;
  /* The column has no side padding of its own, so a sticky child would let the
     text it covers show through at the edges as it passes. */
  margin-inline: calc(var(--gut) * -1);
  padding-inline: var(--gut);
}

/* The rule between sections, which is the system's own device for exactly this
   — `.ep-block + .ep-block` does it for the page and this does it for the form.
   The gap shrinks because the rule is now doing the separating; 40px of air AND
   a rule is a rule nobody needed. */
.ep-editor-form {
  gap: 28px;
}
.ep-editor-form > section + section {
  border-block-start: var(--rule) solid var(--w-hair);
  padding-block-start: 28px;
}

/* ---- the plan tier ------------------------------------------------------
   One ramp, paper → lime → accent → ink, light to dark as the plan grows, so
   the ramp itself says which way is bigger before a single number is read. It
   is the SAME four values in the card grid and in the comparison table, which
   is the whole reason it is a vocabulary rather than four colour choices: a
   buyer who has picked a card out of the grid finds the same colour heading
   the same plan's column further down the page.

   The band is a FILL and the border only echoes it. That asymmetry is forced
   rather than chosen — `paper` at the bottom of the ramp is #e9eef2, which
   reads perfectly as a filled strip and measures about 1.05:1 as a hairline on
   the panel it sits on, i.e. nothing. So the identity is carried by the thing
   that can carry it at every step of the ramp, and the border is decoration
   that agrees with it. The lowest step keeps the neutral --w-line every other
   panel on the site uses, because "no colour" is what the free plan IS. */
.ep-plan-tier {
  overflow: hidden;
  padding: 0;
}
.ep-plan-tier-band {
  padding: 10px clamp(14px, 2vw, 22px);
  border-block-end: var(--rule) solid currentColor;
}
.ep-plan-tier-body {
  padding: clamp(14px, 2vw, 22px);
  display: flex;
  flex-direction: column;
  flex: 1;
}
.ep-account-plan {
  display: inline-flex;
  align-items: center;
  padding: 5px 10px;
  border: 1px solid currentColor;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
}
.ep-account-plan:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
.ep-subscription-card[data-tier="paper"] { --subscription-fill: var(--paper); --subscription-ink: var(--ink); }
.ep-subscription-card[data-tier="lime"] { --subscription-fill: var(--fill-accent); --subscription-ink: var(--ink); }
.ep-subscription-card[data-tier="accent"] { --subscription-fill: var(--accent-fill); --subscription-ink: var(--on-accent); }
.ep-subscription-card[data-tier="ink"] { --subscription-fill: var(--band); --subscription-ink: var(--on-band); }
.ep-subscription-heading {
  background: var(--subscription-fill);
  color: var(--subscription-ink);
}
.ep-subscription-heading input { accent-color: var(--subscription-ink); }
.ep-subscription-details {
  background: color-mix(in srgb, var(--subscription-fill) 12%, var(--surface));
}
.ep-plan-tier[data-tier="paper"] .ep-plan-tier-band,
.ep-account-plan[data-tier="paper"] {
  background: var(--paper);
  color: var(--ink);
}
.ep-plan-tier[data-tier="lime"] .ep-plan-tier-band,
.ep-account-plan[data-tier="lime"] {
  background: var(--fill-accent);
  color: var(--ink);
}
.ep-plan-tier[data-tier="accent"] .ep-plan-tier-band,
.ep-account-plan[data-tier="accent"] {
  background: var(--accent-fill);
  color: var(--on-accent);
}
.ep-plan-tier[data-tier="ink"] .ep-plan-tier-band,
.ep-account-plan[data-tier="ink"] {
  background: var(--band);
  color: var(--on-band);
}
/* Every card is bordered, and three of the four in their own colour. It used to
   be one blue ring on Growth and plain grey on the other three, which said
   "this one is a plan and those are alternatives". */
.ep-plan-tier[data-tier="lime"] {
  border-color: var(--fill-accent);
}
.ep-plan-tier[data-tier="accent"] {
  border-color: var(--accent-fill);
}
.ep-plan-tier[data-tier="ink"] {
  border-color: var(--ink);
}

/* The four calls to action, at one height.
 *
 * They live in four separate grid items, so nothing makes them agree on their
 * own. The grid stretches the CARDS to match and stops there: at four columns
 * each card is about 280px of usable width, and at poster scale — 40px of
 * display type — "Stay visible" took one line while "Grow my AI presence" took
 * three. 88px beside 168px, four buttons at two sizes, reading as two different
 * kinds of offer.
 *
 * The fix is both halves. Form scale first, because 40px of type in a 280px
 * card is the same over-scaling `.ep-bar-form` exists for, and it is what made
 * the labels wrap three deep in the first place — at 20px every one of them
 * fits a single line. Then a two-line floor, so the one translation that does
 * wrap does not leave its card's button taller than the other three: all four
 * render at the two-line height whether they need it or not.
 *
 * Computed from `.ep-bar-form`'s own clamps rather than written as a number, so
 * it tracks the bar if those ever move. The label centres in the extra room and
 * the arrow stays pinned to the far edge, which is what keeps the four reading
 * as one row of controls. */
.ep-bar-plan {
  min-block-size: calc(
    2 * clamp(16px, 2vw, 20px) + 2 * clamp(11px, 1.4vw, 14px)
  );
}

/* A panel that is only a panel where a panel helps. On a phone the /pricing
   ladder holds four .ep-plan-card boxes; putting them inside one more bordered,
   rounded box is a card inside a card, which is the one nesting this system
   bans. From 768px the same wrapper holds a four-column table instead, and a
   table does want a box around it. Mobile-first: no box by default, the box
   added at the width that earns it. */
.ep-panel-wide {
  display: flow-root;
}
@media (min-width: 768px) {
  .ep-panel-wide {
    background: var(--w-panel);
    border: var(--rule) solid var(--w-line);
    border-radius: var(--r-panel);
    padding: clamp(14px, 2vw, 22px);
  }
}

/* ── the assistant example cards ──────────────────────────────────────────────
   Reported as "it is not clear this is a chat with an AI". It was not: the card
   was an eyebrow, a name and a sentence, which is the shape of a quote and not
   the shape of a conversation. A conversation needs two speakers, two turns and
   two sides — so it gets them.

   Bubbles have a radius. That is new here and it is allowed: the owner lifted
   the ban on 2026-08-22, and the one narrow rule that remains is his — no card
   inside a card, which is why the bubbles sit directly on the panel's own ground
   with no second bordered box between them. */
.ep-chat {
  display: grid;
  gap: 10px;
}
.ep-chat-turn {
  display: grid;
  gap: 4px;
  max-inline-size: 92%;
}
/* The person's turn leads; the assistant's answers back. Logical properties, so
   the conversation runs the right way round in Arabic and Hebrew instead of
   mirroring into nonsense. */
.ep-chat-turn[data-who="user"] {
  justify-self: end;
  text-align: end;
}
.ep-chat-turn[data-who="ai"] {
  justify-self: start;
}
.ep-chat-who {
  font-size: var(--w-small-size);
  font-weight: 700;
  color: var(--w-faint);
}
.ep-chat-bubble {
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  padding: 10px 14px;
  font-size: var(--w-body-size);
  line-height: 1.45;
}
.ep-chat-turn[data-who="user"] .ep-chat-bubble {
  background: var(--paper);
  /* The corner nearest the speaker squares off. One flattened corner is what a
     tail does in a rounded system, without drawing a tail. */
  border-end-end-radius: 2px;
}
.ep-chat-turn[data-who="ai"] .ep-chat-bubble {
  background: var(--surface);
  border-end-start-radius: 2px;
}
/* The answer names somebody, and the name is the point of the whole card. */
.ep-chat-bubble strong {
  font-family: var(--ep-display);
  font-weight: 900;
}


/* ── the pastel-blue panel ────────────────────────────────────────────────────
   --blue was defined and reserved with zero call sites from the day the palette
   was written. This is the job it gets: the ordinary-search card, so the two
   ways a person turns up are told apart by ground as well as by heading.

   Measured on #a3c2de — ink 10.62:1, --w-mute 5.05:1, both fine; --w-faint is
   3.08:1 and must never appear on it, which is why the rules inside this panel
   set the body colour rather than the faint one. */
.ep-panel-blue {
  background: var(--fill-info);
}
.ep-panel-blue .ep-label,
.ep-panel-blue .ep-eyebrow {
  color: var(--ink);
}

/* ── the conversation carousel ───────────────────────────────────────────────
   One card at a time. Three abreast made three conversations compete for one
   glance, and at 390px they became a column so long the third was never
   reached.

   The dots are the pause mechanism, and a real one: pressing any of them stops
   the advance for good rather than until the next tick. That is what lets this
   auto-advance without a separate Pause button beside it. */
.ep-carousel-view {
  overflow: hidden;
}
.ep-carousel-track {
  display: flex;
  transition: transform var(--dur-field) var(--ease-io);
}
.ep-carousel-slide {
  flex: 0 0 100%;
  min-inline-size: 0;
  /* The slides off to the side are still in the DOM and still focusable-safe;
     the padding keeps a focus ring from being clipped by the overflow above. */
  padding: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .ep-carousel-track {
    transition: none;
  }
}

.ep-carousel-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-block-start: 16px;
}
.ep-carousel-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 44px;
  min-block-size: 44px;
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  background: transparent;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.ep-carousel-dots {
  display: flex;
  gap: 4px;
}
/* 44px of target around a 12px dot, bought with padding rather than size so the
   drawn dot does not grow. background-clip keeps the paint inside the content
   box, so the padding stays invisible and stays tappable. */
.ep-carousel-dot {
  inline-size: 12px;
  block-size: 12px;
  padding: 16px;
  margin: 0;
  border: var(--rule) solid var(--ink);
  border-radius: 999px;
  background: transparent;
  background-clip: content-box;
  box-sizing: content-box;
  cursor: pointer;
}
.ep-carousel-dot[data-active] {
  background: var(--ink);
  background-clip: content-box;
}

/* ── without / with ──────────────────────────────────────────────────────────
   The two halves used to sit on the same paper with the same border, told apart
   by a square glyph — so the reader had to READ to learn which column they were
   in. The ground says it now, and the marks confirm rather than announce.

   Ink and lime rather than two new tints: both already carry jobs on this page,
   and the lime half is the half the reader is being asked to choose, which is
   the same thing lime says everywhere else here. */
.ep-vs {
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  padding: clamp(18px, 2.6vw, 28px);
  display: flow-root;
}
.ep-vs[data-side="without"] {
  /* Not pure ink: a full-strength black card beside a lime one reads as the
     louder of the two, and the loud one should be the half being sold. */
  background: var(--vs-dead);
  color: var(--vs-dead-ink);
}
.ep-vs[data-side="with"] {
  background: var(--fill-accent);
  color: var(--ink);
}

.ep-vs-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block-end: clamp(14px, 2vw, 20px);
  border-block-end: var(--rule) solid currentColor;
}
/* The badge inverts its own card so the mark reads as a stamp on the ground
   rather than as a hole in it. */
.ep-vs-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  flex: none;
  border-radius: 999px;
  border: var(--rule) solid currentColor;
  font-size: 20px;
  line-height: 1;
}
.ep-vs[data-side="without"] .ep-vs-badge {
  background: var(--paper);
  color: var(--ink);
}
.ep-vs[data-side="with"] .ep-vs-badge {
  background: var(--paper);
  color: var(--ink);
}
.ep-vs-title {
  font-family: var(--ep-display);
  font-size: clamp(19px, 2.2vw, 26px);
  font-weight: 800;
  letter-spacing: -0.02em;
}

.ep-vs-list {
  display: grid;
  gap: clamp(14px, 2vw, 20px);
  margin-block-start: clamp(16px, 2.2vw, 22px);
}
/* Two lines is fine here, and that is the point of moving to cards: inside a
   card with its own ground a wrapped item is a paragraph shape, where in the
   flat list it read as a mistake. The German and Korean items can say the whole
   thing again. */
.ep-vs-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: var(--w-body-size);
  font-weight: 600;
  line-height: 1.35;
}
.ep-vs-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 22px;
  block-size: 22px;
  flex: none;
  margin-block-start: 1px;
  border: var(--rule) solid currentColor;
  font-size: 14px;
  line-height: 1;
}
/* The good half's marks are filled, so the two columns differ in weight as well
   as in glyph — a ✓ and an ✕ are the same shape to somebody who cannot tell red
   from green, and neither colour is doing the work here anyway. */
.ep-vs-mark[data-on] {
  background: var(--ink);
  color: var(--fill-accent);
}

/* Where the pair lands. Full width under both cards, in the lime of the half
   being chosen. */
.ep-vs-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-block-start: clamp(16px, 2.4vw, 24px);
  min-block-size: 64px;
  padding: 14px clamp(18px, 2.6vw, 28px);
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  /* One of the two places in the system allowed a gradient, and this is why it
     is allowed here: the bar is the ACTION and the card above it is the
     argument. On a dark page a flat fill would read as the card's bottom edge.
     A gradient is the one treatment nothing else on the page wears, so the
     action cannot be mistaken for part of what it follows.
     Label is pure white, not --ink: it sits on --accent-fill at one end and
     --violet at the other, 5.17:1 and 5.70:1, and 5.77:1 where they meet. */
  /* The colour is stated under the gradient, not instead of it. A gradient is a
     background-IMAGE: it is dropped when printing, replaced under forced
     colours, and absent for the moment before it paints — and in every one of
     those the cream label would be cream on cream. The flat fill underneath is
     what the label is actually measured against, 7.04:1. */
  background-color: var(--accent-fill);
  background-image: var(--grad-cta);
  color: var(--on-accent);
  border-color: transparent;
  font-family: var(--ep-display);
  font-size: clamp(19px, 2.4vw, 30px);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-decoration: none;
}
.ep-vs-cta-end {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  flex: none;
}
.ep-vs-cta-arrow {
  font-size: 24px;
  line-height: 1;
}

/* ── the visibility board ────────────────────────────────────────────────────
   One component, two homes: the landing page shows it filled with a worked
   example, the console will show it filled with the owner's own figures. Which
   is what keeps the numbers on the marketing page honest — they are part of
   depicting the screen a customer gets, not a claim about somebody's results.

   Ink and blue carry it. Lime is not used here: lime is emphasis without state
   and every mark on this board means something specific. */
.ep-board {
  display: grid;
  gap: clamp(14px, 2vw, 20px);
}
.ep-board-metrics {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(12px, 1.6vw, 16px);
}
@media (min-width: 620px) {
  .ep-board-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.ep-metric,
.ep-board-panel {
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  background: var(--surface);
  padding: clamp(14px, 2vw, 20px);
}
.ep-metric-label {
  font-size: var(--w-small-size);
  font-weight: 700;
}
.ep-metric-note {
  font-size: var(--w-small-size);
  color: var(--w-mute);
  margin-block-start: 2px;
}
.ep-metric-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-block-start: 10px;
}
.ep-metric-value {
  font-size: clamp(28px, 4vw, 44px);
  line-height: 1;
}
.ep-metric-delta {
  font-size: var(--w-small-size);
  font-weight: 700;
  color: var(--ok);
  margin-block-start: 6px;
}
.ep-spark {
  inline-size: 92px;
  block-size: 32px;
  flex: none;
}
.ep-spark path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}

.ep-board-h {
  font-family: var(--ep-display);
  font-size: clamp(18px, 2.2vw, 24px);
  font-weight: 800;
  letter-spacing: -0.02em;
}
.ep-board-note {
  font-size: var(--w-small-size);
  color: var(--w-mute);
  margin-block-start: 4px;
}

.ep-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-block-start: 14px;
  font-size: var(--w-small-size);
  font-weight: 700;
}
.ep-legend li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.ep-legend-dot {
  inline-size: 12px;
  block-size: 12px;
  border-radius: 999px;
  border: 2px solid var(--ink);
}
.ep-legend li[data-role="you"] .ep-legend-dot {
  background: var(--ink);
}

/* The chart. A y axis with real ticks and an x axis with real periods, because
   this is a picture OF the dashboard rather than a diagram about it. */
.ep-chart {
  display: flex;
  gap: 10px;
  margin-block-start: 12px;
}
.ep-chart-y {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  font-size: var(--w-small-size);
  color: var(--w-mute);
  /* The x-axis row below the plot, so the ticks line up with the plot and not
     with the plot plus its labels. */
  padding-block-end: 22px;
  flex: none;
}
.ep-chart-plot {
  flex: 1 1 auto;
  min-inline-size: 0;
}
.ep-chart-svg {
  inline-size: 100%;
  block-size: clamp(150px, 22vw, 240px);
  display: block;
}
.ep-chart-grid {
  stroke: var(--w-hair);
  stroke-width: 1;
  stroke-dasharray: 3 4;
  vector-effect: non-scaling-stroke;
}
.ep-chart-fill {
  fill: var(--accent);
  opacity: 0.55;
}
.ep-chart-line {
  fill: none;
  stroke-width: 2.2;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
}
.ep-chart-line[data-role="you"] {
  stroke: var(--ink);
}
.ep-chart-line[data-role="other"] {
  stroke: var(--w-mute);
  stroke-width: 1.6;
  stroke-dasharray: 5 4;
}
.ep-chart-x {
  display: flex;
  justify-content: space-between;
  margin-block-start: 6px;
  font-size: var(--w-small-size);
  color: var(--w-mute);
}

.ep-board-event {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-block-start: 16px;
  padding-block-start: 16px;
  border-block-start: var(--rule) solid var(--w-hair);
  font-weight: 600;
}
.ep-board-event-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 34px;
  block-size: 34px;
  flex: none;
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
}

.ep-models {
  display: grid;
  gap: 14px;
  margin-block-start: 14px;
}
.ep-models-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.ep-models-name {
  font-family: var(--ep-display);
  font-size: clamp(16px, 1.9vw, 20px);
  font-weight: 800;
}
.ep-models-rate {
  font-size: clamp(16px, 1.9vw, 20px);
}
.ep-models-bar {
  block-size: 10px;
  margin-block-start: 6px;
  border: var(--rule) solid var(--ink);
  border-radius: 999px;
  overflow: hidden;
}
.ep-models-bar > span {
  display: block;
  block-size: 100%;
  background: var(--accent);
}

/* ── the desktop ladder ──────────────────────────────────────────────────────
   The phone got one bordered card per plan with a filled header band; the table
   kept none of that, so on a wide screen the same complaint applied turned
   ninety degrees — the boundary between two plan COLUMNS was invisible and a
   reader tracking one plan down fifteen rows had nothing to follow.

   Same four bands as the cards, in the same order, so the two shapes are one
   design seen twice rather than two designs. The columns then get a faint tint
   of their own band so the eye can run down one without counting across. */
.ep-ladder-head {
  padding: 10px 14px;
  text-align: start;
  font-family: var(--ep-display);
  font-size: clamp(15px, 1.5vw, 19px);
  font-weight: 800;
  letter-spacing: -0.01em;
  border-start-start-radius: var(--r-panel);
  border-start-end-radius: var(--r-panel);
}
.ep-ladder-head[data-tier="paper"] {
  background: var(--paper);
  color: var(--ink);
}
.ep-ladder-head[data-tier="lime"] {
  background: var(--fill-accent);
  color: var(--ink);
}
.ep-ladder-head[data-tier="accent"] {
  background: var(--accent-fill);
  color: var(--on-accent);
}
.ep-ladder-head[data-tier="ink"] {
  background: var(--band);
  color: var(--on-band);
}

.ep-ladder-cell {
  padding: 12px 14px;
}
/* A tint, not the band. The header states which column this is; the body only
   has to keep the eye inside it, and a full-strength column would drown the
   values it exists to carry. --w-hair is the same rule that divides the rows,
   so the grid stays one weight. */
.ep-ladder-cell[data-tier="lime"] {
  background: color-mix(in srgb, var(--fill-accent) 42%, transparent);
}
.ep-ladder-cell[data-tier="accent"] {
  background: color-mix(in srgb, var(--accent-fill) 12%, transparent);
}
.ep-ladder-cell[data-tier="ink"] {
  background: color-mix(in srgb, var(--ink) 7%, transparent);
}
/* The vertical seam. Every cell of every column but the first carries it, which
   is what makes a COLUMN readable as a column rather than a row of cells that
   happen to line up. */
.ep-ladder-head + .ep-ladder-head,
.ep-ladder-cell + .ep-ladder-cell {
  border-inline-start: 1px solid var(--w-hair);
}

/* ── the theme control ───────────────────────────────────────────────────────
   A 44px target with a 24px mark inside it, because the mark is what should be
   read and the target is what should be hit — they are not the same size and
   pretending they are is how a header ends up with 28px buttons.
   Everything is currentColor, so the control needs no rule of its own in either
   theme: it is already whatever the bar it sits in is lettered in. */
.ep-theme {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  flex: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  border-radius: var(--r-panel);
}

.ep-theme:disabled {
  cursor: default;
  /* Not hidden and not faded: the box is held so the row does not jump under a
     finger already on its way down, and one frame of a dimmed icon would read
     as a broken control rather than a loading one. */
  opacity: 1;
}

.ep-theme svg {
  inline-size: 24px;
  block-size: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The sun's disc and the crescent are filled; the rays are drawn. Two
   different jobs for one colour.

   Filled, both. The moon used to be drawn as a 2px outline while the sun was
   solid, so switching to dark looked like the button had emptied itself. Same
   ink, same weight, two marks. There was a third — a half-filled disc for the
   "follows your device" state — and it went with the state. */
.ep-theme svg circle,
.ep-theme svg .ep-theme-moon {
  fill: currentColor;
  stroke: none;
}

.ep-theme .ep-theme-rays path {
  fill: none;
}

.ep-theme:hover svg {
  transform: scale(1.06);
}

.ep-theme svg {
  transition: transform var(--dur-state) var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .ep-theme svg {
    transition-duration: 1ms;
  }
}

/* ---- the project tabs ----------------------------------------------------
   Browser tabs, because that is the shape everybody already knows — and the
   colour is the working part rather than decoration. With one page a tab strip
   is a label; with five it is a target, and a name in 15px is a slower one than
   a field of colour. The active tab's tint floods the console behind it, so a
   page is picked by the colour of the room it opens.

   No rule under the row. There was one, and it drew a hard line across the
   window between two grounds that are now the same colour — the tab and the
   console it opens are one surface, and a seam through it said they were two. */
.ep-projects {
  padding-block-start: 8px;
  background: var(--console-tint, var(--paper));
}

.ep-projects-row {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: thin;
}

/* The open tab. Wide, joined to the console below it, and the only one wearing
   its name — the page being worked on is the one whose name matters. */
.ep-project-tab {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  border: 0;
  border-start-start-radius: var(--r-panel);
  border-start-end-radius: var(--r-panel);
  background: var(--tab-tint, var(--paper));
}

.ep-project-tab-name {
  display: inline-flex;
  align-items: center;
  min-height: 56px;
  max-width: 28ch;
  overflow: hidden;
  padding-inline: 22px;
  font-family: var(--ep-display);
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ink);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* A closed tab. One letter in its own colour, in a rounded square — enough to
   aim at and to tell apart, and it spends no width on a page nobody is reading.
   The full name is still the accessible name; only the drawing is short. */
.ep-project-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-inline-size: 100px;
  max-inline-size: 22ch;
  block-size: 48px;
  padding-inline: 16px;
  align-self: flex-end;
  border: 0;
  border-radius: var(--r-panel) var(--r-panel) 0 0;
  background: var(--tab-tint, var(--paper));
  font-family: var(--ep-display);
  font-size: 17px;
  font-weight: 800;
  color: var(--ink);
  opacity: 0.85;
}

.ep-project-chip:hover {
  opacity: 1;
}

.ep-project-tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 44px;
  padding-inline-end: 12px;
  font-size: 18px;
  line-height: 1;
  color: var(--ink);
  opacity: 0.65;
}

.ep-project-tab-close:hover {
  opacity: 1;
}

.ep-project-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-inline-start: 2px;
  border-start-start-radius: var(--r-panel);
  border-start-end-radius: var(--r-panel);
  font-size: 20px;
  line-height: 1;
  color: var(--paper);
  background: var(--ink);
  border: var(--rule) solid var(--ink);
  border-radius: 8px;
  font-weight: 800;
  opacity: 1;
}

.ep-project-add:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.ep-project-add:hover {
  opacity: 1;
}

/* ---- a tab's colour ------------------------------------------------------
   Six tints, each a fill token mixed into the page ground. Built rather than
   picked, so they stay tints instead of becoming second surfaces, and so they
   follow the theme: the same class is a pale wash on paper and a deep one in
   the dark, where a fixed hex would be a light patch in a dark room.

   Two custom properties on purpose. --tab-tint colours the tab itself;
   --console-tint is read by the console's own ground, and the shell sets it
   from whichever tab is active. One value, two places that need it. */
.ep-tint-0 { --tab-tint: var(--paper); }
.ep-tint-1 { --tab-tint: color-mix(in srgb, var(--fill-person) 60%, var(--paper)); }
.ep-tint-2 { --tab-tint: color-mix(in srgb, var(--fill-accent) 60%, var(--paper)); }
.ep-tint-3 { --tab-tint: color-mix(in srgb, var(--fill-info) 60%, var(--paper)); }
.ep-tint-4 { --tab-tint: color-mix(in srgb, var(--signal) 22%, var(--paper)); }
.ep-tint-5 { --tab-tint: color-mix(in srgb, var(--accent) 22%, var(--paper)); }

/* The console takes the active tab's tint, which is what makes the colour a
   way of telling pages apart rather than a stripe at the top of one. */
.ep-console-tinted {
  --console-tint: var(--tab-tint, var(--paper));
  background: var(--console-tint);
}

@media (forced-colors: none) {
  .ep-console-tinted > .ep-nav {
    background: var(--console-tint);
  }
}

/* ---- renaming a tab and choosing its colour ----------------------------- */
.ep-project-editor {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 20px;
  padding-block: 16px;
}

.ep-project-field {
  display: grid;
  gap: 6px;
}

.ep-project-name-input {
  min-block-size: 44px;
  inline-size: min(280px, 100%);
  padding: 8px 12px;
  border: var(--rule) solid var(--w-line);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
}

.ep-project-name-input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.ep-swatches {
  display: flex;
  gap: 8px;
}

.ep-swatch {
  inline-size: 32px;
  block-size: 32px;
  border-radius: 999px;
  border: var(--rule) solid var(--w-line);
  background: var(--tab-tint, var(--paper));
}

/* Selected by a ring rather than by a tick: a tick inside a 32px circle of a
   pale colour is a shape nobody can see. */
.ep-swatch[aria-checked="true"] {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--ink);
}

/* ---- the OR rule ---------------------------------------------------------
   A rule with the word sitting IN it rather than beside it, so two routes read
   as alternatives instead of as a form and a footnote underneath it.

   Grid rather than a pseudo-element trick: two 1fr tracks of rule and the word
   between them centres itself at any word length, which matters when "OR" is
   "ИЛИ", "または" or "או". */
.ep-or {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
}

.ep-or::before,
.ep-or::after {
  content: "";
  block-size: var(--rule);
  background: var(--ink);
  opacity: 0.35;
}

.ep-or-word {
  font-family: var(--ep-ui);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--w-mute);
}

/* ---- the modal -----------------------------------------------------------
   A native <dialog> opened with showModal(), so the focus trap, Escape, the
   inertness of everything behind it and the top layer all come from the
   browser. The only thing added here is how it looks.

   Centred with `margin: auto` on the fixed positioning of the top layer, which
   is the one centring technique that does not fight the browser's own. */
.ep-modal {
  margin: auto;
  max-inline-size: min(30rem, calc(100vw - 2 * var(--gut)));
  padding: clamp(20px, 3vw, 32px);
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  background: var(--surface);
  color: var(--ink);
}

/* The blur belongs on ::backdrop and nowhere else: a filter on an ancestor
   would blur the dialog along with the page, and a blurred overlay div would
   sit under the top layer rather than over the console. The colour is carried
   too, because a blur alone leaves text legible enough to read through. */
.ep-modal::backdrop {
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  backdrop-filter: blur(6px);
}

/* Nothing behind it should move while it is open. */
body:has(dialog[open]) {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .ep-modal::backdrop {
    backdrop-filter: none;
  }
}

/* ---- the editor's blocks -------------------------------------------------
   Four pastel panels, each folding on its own. The grounds are the same three
   fill tokens whole marketing blocks are flooded with, plus the raised surface
   for the fourth — so the console borrows the site's palette instead of
   inventing one, and ink keeps the contrast figures already measured for it. */
.ep-editor-block {
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  padding: clamp(16px, 2.2vw, 26px);
  color: var(--ink);
}

.ep-editor-block + .ep-editor-block {
  margin-block-start: 18px;
}

.ep-editor-block-person { background: var(--fill-person); }
.ep-editor-block-accent { background: var(--fill-accent); }
.ep-editor-block-info   { background: var(--fill-info); }
.ep-editor-block-plain  { background: var(--surface-hi); }

.ep-editor-block-summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  min-height: 44px;
  cursor: pointer;
  list-style: none;
}

.ep-editor-block-summary::-webkit-details-marker {
  display: none;
}

/* The triangle is drawn rather than borrowed, so it can be the one thing that
   rotates and so it survives a list-style reset. */
.ep-editor-block-summary::after {
  content: "";
  flex: 0 0 auto;
  inline-size: 10px;
  block-size: 10px;
  margin-inline-start: auto;
  border-inline-end: 2px solid currentColor;
  border-block-end: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 150ms ease;
}

.ep-editor-block[open] > .ep-editor-block-summary::after {
  transform: rotate(-135deg);
}

@media (prefers-reduced-motion: reduce) {
  .ep-editor-block-summary::after {
    transition: none;
  }
}

.ep-editor-block-state {
  flex: 0 0 auto;
  font-family: var(--ep-ui);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.62;
}

.ep-editor-block-state[data-dirty] {
  opacity: 1;
}

.ep-editor-block-body {
  margin-block-start: 18px;
}

.ep-editor-block-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-block-start: 22px;
}

.ep-editor-block-save {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 22px;
  border: var(--rule) solid var(--ink);
  border-radius: var(--r-panel);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--ep-display);
  font-size: 15px;
  font-weight: 800;
}

.ep-editor-block-save:disabled {
  background: transparent;
  color: var(--ink);
  opacity: 0.55;
  cursor: not-allowed;
}

.ep-editor-block-why {
  font-family: var(--ep-ui);
  font-size: 13px;
  color: var(--ink);
  opacity: 0.8;
}

/* ---- the preview drawer --------------------------------------------------
   A sheet on the inline-end edge, arriving from the side the preview used to
   occupy permanently. Native <dialog> underneath, so the focus trap, Escape and
   the top layer are the browser's rather than three things to get right here. */
.ep-drawer {
  margin: 0 0 0 auto;
  inline-size: min(30rem, 100vw);
  block-size: 100dvh;
  max-block-size: 100dvh;
  padding: clamp(18px, 2.6vw, 30px);
  overflow-y: auto;
  border: 0;
  border-inline-start: var(--rule) solid var(--ink);
  background: var(--surface);
  color: var(--ink);
}

/* Mirrors for Hebrew and Arabic: `margin-inline-start: auto` puts the sheet on
   the end edge, which is the right one in both directions. */
.ep-drawer:dir(rtl) {
  margin: 0 auto 0 0;
}

.ep-drawer::backdrop {
  background: color-mix(in srgb, var(--ink) 45%, transparent);
  backdrop-filter: blur(4px);
}

.ep-drawer-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

@media (prefers-reduced-motion: reduce) {
  .ep-drawer::backdrop {
    backdrop-filter: none;
  }
}

/* The pencil on the open tab. Half-strength until the tab is hovered or
   focused, because it is a hint and not a second thing to read — at full
   contrast beside a name it competes with it. */
.ep-project-tab-mark {
  inline-size: 16px;
  block-size: 16px;
  flex: 0 0 auto;
  margin-inline-start: 10px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.45;
  transition: opacity 120ms ease;
}

.ep-project-tab-name:hover .ep-project-tab-mark,
.ep-project-tab-name:focus-visible .ep-project-tab-mark,
.ep-project-tab-name[aria-expanded="true"] .ep-project-tab-mark {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .ep-project-tab-mark {
    transition: none;
  }
}

/*!*************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[12].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[12].use[3]!./app/globals.css ***!
  \*************************************************************************************************************************************************************************************************************************************************************/
*, ::before, ::after{
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

::backdrop{
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

/*
! tailwindcss v3.4.13 | MIT License | https://tailwindcss.com
*/

/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/

*,
::before,
::after {
  box-sizing: border-box; /* 1 */
  border-width: 0; /* 2 */
  border-style: solid; /* 2 */
  border-color: #e5e7eb; /* 2 */
}

::before,
::after {
  --tw-content: '';
}

/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/

html,
:host {
  line-height: 1.5; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
  -moz-tab-size: 4; /* 3 */
  -o-tab-size: 4;
     tab-size: 4; /* 3 */
  font-family: var(--font-sans), Inter, system-ui, sans-serif; /* 4 */
  font-feature-settings: normal; /* 5 */
  font-variation-settings: normal; /* 6 */
  -webkit-tap-highlight-color: transparent; /* 7 */
}

/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/

body {
  margin: 0; /* 1 */
  line-height: inherit; /* 2 */
}

/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/

hr {
  height: 0; /* 1 */
  color: inherit; /* 2 */
  border-top-width: 1px; /* 3 */
}

/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/

abbr:where([title]) {
  -webkit-text-decoration: underline dotted;
          text-decoration: underline dotted;
}

/*
Remove the default font size and weight for headings.
*/

h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}

/*
Reset links to optimize for opt-in styling instead of opt-out.
*/

a {
  color: inherit;
  text-decoration: inherit;
}

/*
Add the correct font weight in Edge and Safari.
*/

b,
strong {
  font-weight: bolder;
}

/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/

code,
kbd,
samp,
pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */
  font-feature-settings: normal; /* 2 */
  font-variation-settings: normal; /* 3 */
  font-size: 1em; /* 4 */
}

/*
Add the correct font size in all browsers.
*/

small {
  font-size: 80%;
}

/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/

table {
  text-indent: 0; /* 1 */
  border-color: inherit; /* 2 */
  border-collapse: collapse; /* 3 */
}

/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/

button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-feature-settings: inherit; /* 1 */
  font-variation-settings: inherit; /* 1 */
  font-size: 100%; /* 1 */
  font-weight: inherit; /* 1 */
  line-height: inherit; /* 1 */
  letter-spacing: inherit; /* 1 */
  color: inherit; /* 1 */
  margin: 0; /* 2 */
  padding: 0; /* 3 */
}

/*
Remove the inheritance of text transform in Edge and Firefox.
*/

button,
select {
  text-transform: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/

button,
input:where([type='button']),
input:where([type='reset']),
input:where([type='submit']) {
  -webkit-appearance: button; /* 1 */
  background-color: transparent; /* 2 */
  background-image: none; /* 2 */
}

/*
Use the modern Firefox focus style for all focusable elements.
*/

:-moz-focusring {
  outline: auto;
}

/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/

:-moz-ui-invalid {
  box-shadow: none;
}

/*
Add the correct vertical alignment in Chrome and Firefox.
*/

progress {
  vertical-align: baseline;
}

/*
Correct the cursor style of increment and decrement buttons in Safari.
*/

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/

[type='search'] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}

/*
Remove the inner padding in Chrome and Safari on macOS.
*/

::-webkit-search-decoration {
  -webkit-appearance: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/

::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}

/*
Add the correct display in Chrome and Safari.
*/

summary {
  display: list-item;
}

/*
Removes the default spacing and border for appropriate elements.
*/

blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
  margin: 0;
}

fieldset {
  margin: 0;
  padding: 0;
}

legend {
  padding: 0;
}

ol,
ul,
menu {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
Reset default styling for dialogs.
*/

dialog {
  padding: 0;
}

/*
Prevent resizing textareas horizontally by default.
*/

textarea {
  resize: vertical;
}

/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/

input::-moz-placeholder, textarea::-moz-placeholder {
  opacity: 1; /* 1 */
  color: #9ca3af; /* 2 */
}

input::placeholder,
textarea::placeholder {
  opacity: 1; /* 1 */
  color: #9ca3af; /* 2 */
}

/*
Set the default cursor for buttons.
*/

button,
[role="button"] {
  cursor: pointer;
}

/*
Make sure disabled buttons don't get the pointer cursor.
*/

:disabled {
  cursor: default;
}

/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
   This can trigger a poorly considered lint error in some tools but is included by design.
*/

img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
  display: block; /* 1 */
  vertical-align: middle; /* 2 */
}

/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/

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

/* Make elements with the HTML hidden attribute stay hidden by default */

[hidden] {
  display: none;
}
.container{
  width: 100%;
}
@media (min-width: 640px){

  .container{
    max-width: 640px;
  }
}
@media (min-width: 768px){

  .container{
    max-width: 768px;
  }
}
@media (min-width: 1024px){

  .container{
    max-width: 1024px;
  }
}
@media (min-width: 1280px){

  .container{
    max-width: 1280px;
  }
}
@media (min-width: 1536px){

  .container{
    max-width: 1536px;
  }
}
.sr-only{
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
.pointer-events-none{
  pointer-events: none;
}
.visible{
  visibility: visible;
}
.invisible{
  visibility: hidden;
}
.collapse{
  visibility: collapse;
}
.static{
  position: static;
}
.fixed{
  position: fixed;
}
.absolute{
  position: absolute;
}
.relative{
  position: relative;
}
.sticky{
  position: sticky;
}
.inset-x-0{
  left: 0px;
  right: 0px;
}
.bottom-0{
  bottom: 0px;
}
.top-full{
  top: 100%;
}
.isolate{
  isolation: isolate;
}
.z-20{
  z-index: 20;
}
.z-30{
  z-index: 30;
}
.z-\[100\]{
  z-index: 100;
}
.m-0{
  margin: 0px;
}
.mx-auto{
  margin-left: auto;
  margin-right: auto;
}
.my-0{
  margin-top: 0px;
  margin-bottom: 0px;
}
.my-2{
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}
.my-4{
  margin-top: 1rem;
  margin-bottom: 1rem;
}
.my-5{
  margin-top: 1.25rem;
  margin-bottom: 1.25rem;
}
.my-6{
  margin-top: 1.5rem;
  margin-bottom: 1.5rem;
}
.mb-2{
  margin-bottom: 0.5rem;
}
.mb-3{
  margin-bottom: 0.75rem;
}
.me-2{
  margin-inline-end: 0.5rem;
}
.me-auto{
  margin-inline-end: auto;
}
.ms-0{
  margin-inline-start: 0px;
}
.ms-2{
  margin-inline-start: 0.5rem;
}
.ms-4{
  margin-inline-start: 1rem;
}
.ms-auto{
  margin-inline-start: auto;
}
.mt-0\.5{
  margin-top: 0.125rem;
}
.mt-1{
  margin-top: 0.25rem;
}
.mt-1\.5{
  margin-top: 0.375rem;
}
.mt-10{
  margin-top: 2.5rem;
}
.mt-12{
  margin-top: 3rem;
}
.mt-2{
  margin-top: 0.5rem;
}
.mt-2\.5{
  margin-top: 0.625rem;
}
.mt-3{
  margin-top: 0.75rem;
}
.mt-4{
  margin-top: 1rem;
}
.mt-5{
  margin-top: 1.25rem;
}
.mt-6{
  margin-top: 1.5rem;
}
.mt-7{
  margin-top: 1.75rem;
}
.mt-8{
  margin-top: 2rem;
}
.mt-\[clamp\(14px\2c 2\.6vw\2c 26px\)\]{
  margin-top: clamp(14px,2.6vw,26px);
}
.mt-\[clamp\(16px\2c 3vw\2c 28px\)\]{
  margin-top: clamp(16px,3vw,28px);
}
.mt-\[clamp\(16px\2c 3vw\2c 30px\)\]{
  margin-top: clamp(16px,3vw,30px);
}
.mt-\[clamp\(18px\2c 3vw\2c 28px\)\]{
  margin-top: clamp(18px,3vw,28px);
}
.mt-\[clamp\(18px\2c 3vw\2c 32px\)\]{
  margin-top: clamp(18px,3vw,32px);
}
.mt-auto{
  margin-top: auto;
}
.block{
  display: block;
}
.inline-block{
  display: inline-block;
}
.inline{
  display: inline;
}
.flex{
  display: flex;
}
.inline-flex{
  display: inline-flex;
}
.table{
  display: table;
}
.grid{
  display: grid;
}
.contents{
  display: contents;
}
.list-item{
  display: list-item;
}
.hidden{
  display: none;
}
.h-3{
  height: 0.75rem;
}
.h-5{
  height: 1.25rem;
}
.h-6{
  height: 1.5rem;
}
.h-7{
  height: 1.75rem;
}
.h-9{
  height: 2.25rem;
}
.h-auto{
  height: auto;
}
.max-h-\[40vh\]{
  max-height: 40vh;
}
.max-h-\[min\(60vh\2c 22rem\)\]{
  max-height: min(60vh,22rem);
}
.min-h-\[44px\]{
  min-height: 44px;
}
.min-h-\[48px\]{
  min-height: 48px;
}
.min-h-\[52px\]{
  min-height: 52px;
}
.min-h-screen{
  min-height: 100vh;
}
.w-10{
  width: 2.5rem;
}
.w-12{
  width: 3rem;
}
.w-14{
  width: 3.5rem;
}
.w-5{
  width: 1.25rem;
}
.w-\[72px\]{
  width: 72px;
}
.w-\[9ch\]{
  width: 9ch;
}
.w-\[clamp\(84px\2c 12vw\2c 128px\)\]{
  width: clamp(84px,12vw,128px);
}
.w-full{
  width: 100%;
}
.min-w-0{
  min-width: 0px;
}
.min-w-\[11rem\]{
  min-width: 11rem;
}
.min-w-\[16rem\]{
  min-width: 16rem;
}
.min-w-\[44px\]{
  min-width: 44px;
}
.min-w-\[560px\]{
  min-width: 560px;
}
.min-w-\[720px\]{
  min-width: 720px;
}
.min-w-\[min\(100\%\2c 260px\)\]{
  min-width: min(100%,260px);
}
.max-w-3xl{
  max-width: 48rem;
}
.max-w-\[14ch\]{
  max-width: 14ch;
}
.max-w-\[16ch\]{
  max-width: 16ch;
}
.max-w-\[18ch\]{
  max-width: 18ch;
}
.max-w-\[18rem\]{
  max-width: 18rem;
}
.max-w-\[20ch\]{
  max-width: 20ch;
}
.max-w-\[22ch\]{
  max-width: 22ch;
}
.max-w-\[24ch\]{
  max-width: 24ch;
}
.max-w-\[26ch\]{
  max-width: 26ch;
}
.max-w-\[28rem\]{
  max-width: 28rem;
}
.max-w-\[30ch\]{
  max-width: 30ch;
}
.max-w-\[32ch\]{
  max-width: 32ch;
}
.max-w-\[34ch\]{
  max-width: 34ch;
}
.max-w-\[34rem\]{
  max-width: 34rem;
}
.max-w-\[40ch\]{
  max-width: 40ch;
}
.max-w-\[42ch\]{
  max-width: 42ch;
}
.max-w-\[42rem\]{
  max-width: 42rem;
}
.max-w-\[46ch\]{
  max-width: 46ch;
}
.max-w-\[46rem\]{
  max-width: 46rem;
}
.max-w-\[48ch\]{
  max-width: 48ch;
}
.max-w-\[52ch\]{
  max-width: 52ch;
}
.max-w-\[56ch\]{
  max-width: 56ch;
}
.max-w-\[56rem\]{
  max-width: 56rem;
}
.max-w-\[58ch\]{
  max-width: 58ch;
}
.max-w-\[60ch\]{
  max-width: 60ch;
}
.max-w-\[62ch\]{
  max-width: 62ch;
}
.max-w-\[64ch\]{
  max-width: 64ch;
}
.max-w-\[64rem\]{
  max-width: 64rem;
}
.max-w-\[66ch\]{
  max-width: 66ch;
}
.max-w-\[68ch\]{
  max-width: 68ch;
}
.max-w-\[6ch\]{
  max-width: 6ch;
}
.max-w-\[70ch\]{
  max-width: 70ch;
}
.max-w-\[760px\]{
  max-width: 760px;
}
.max-w-full{
  max-width: 100%;
}
.max-w-md{
  max-width: 28rem;
}
.max-w-xl{
  max-width: 36rem;
}
.flex-1{
  flex: 1 1 0%;
}
.flex-none{
  flex: none;
}
.shrink{
  flex-shrink: 1;
}
.shrink-0{
  flex-shrink: 0;
}
.grow{
  flex-grow: 1;
}
.border-collapse{
  border-collapse: collapse;
}
.rotate-180{
  --tw-rotate: 180deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.transform{
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.cursor-pointer{
  cursor: pointer;
}
.resize{
  resize: both;
}
.list-disc{
  list-style-type: disc;
}
.list-none{
  list-style-type: none;
}
.grid-cols-2{
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-\[auto_minmax\(0\2c 1fr\)_auto\]{
  grid-template-columns: auto minmax(0,1fr) auto;
}
.flex-col{
  flex-direction: column;
}
.flex-wrap{
  flex-wrap: wrap;
}
.items-start{
  align-items: flex-start;
}
.items-end{
  align-items: flex-end;
}
.items-center{
  align-items: center;
}
.items-baseline{
  align-items: baseline;
}
.justify-center{
  justify-content: center;
}
.justify-between{
  justify-content: space-between;
}
.justify-items-start{
  justify-items: start;
}
.gap-1{
  gap: 0.25rem;
}
.gap-1\.5{
  gap: 0.375rem;
}
.gap-2{
  gap: 0.5rem;
}
.gap-2\.5{
  gap: 0.625rem;
}
.gap-3{
  gap: 0.75rem;
}
.gap-4{
  gap: 1rem;
}
.gap-5{
  gap: 1.25rem;
}
.gap-7{
  gap: 1.75rem;
}
.gap-8{
  gap: 2rem;
}
.gap-\[clamp\(10px\2c 1\.8vw\2c 18px\)\]{
  gap: clamp(10px,1.8vw,18px);
}
.gap-\[clamp\(14px\2c 2\.4vw\2c 28px\)\]{
  gap: clamp(14px,2.4vw,28px);
}
.gap-\[clamp\(6px\2c 1\.4vw\2c 14px\)\]{
  gap: clamp(6px,1.4vw,14px);
}
.gap-x-1{
  -moz-column-gap: 0.25rem;
       column-gap: 0.25rem;
}
.gap-x-3{
  -moz-column-gap: 0.75rem;
       column-gap: 0.75rem;
}
.gap-x-4{
  -moz-column-gap: 1rem;
       column-gap: 1rem;
}
.gap-x-5{
  -moz-column-gap: 1.25rem;
       column-gap: 1.25rem;
}
.gap-x-6{
  -moz-column-gap: 1.5rem;
       column-gap: 1.5rem;
}
.gap-x-8{
  -moz-column-gap: 2rem;
       column-gap: 2rem;
}
.gap-y-1{
  row-gap: 0.25rem;
}
.gap-y-2{
  row-gap: 0.5rem;
}
.gap-y-3{
  row-gap: 0.75rem;
}
.gap-y-4{
  row-gap: 1rem;
}
.gap-y-8{
  row-gap: 2rem;
}
.space-y-2 > :not([hidden]) ~ :not([hidden]){
  --tw-space-y-reverse: 0;
  margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
}
.space-y-3 > :not([hidden]) ~ :not([hidden]){
  --tw-space-y-reverse: 0;
  margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
}
.space-y-4 > :not([hidden]) ~ :not([hidden]){
  --tw-space-y-reverse: 0;
  margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
}
.space-y-5 > :not([hidden]) ~ :not([hidden]){
  --tw-space-y-reverse: 0;
  margin-top: calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1.25rem * var(--tw-space-y-reverse));
}
.overflow-hidden{
  overflow: hidden;
}
.overflow-x-auto{
  overflow-x: auto;
}
.overflow-y-auto{
  overflow-y: auto;
}
.overscroll-contain{
  overscroll-behavior: contain;
}
.truncate{
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.whitespace-nowrap{
  white-space: nowrap;
}
.whitespace-pre-line{
  white-space: pre-line;
}
.text-wrap{
  text-wrap: wrap;
}
.break-words{
  overflow-wrap: break-word;
}
.break-all{
  word-break: break-all;
}
.rounded{
  border-radius: 0.25rem;
}
.rounded-\[var\(--r-panel\)\]{
  border-radius: var(--r-panel);
}
.rounded-full{
  border-radius: 9999px;
}
.rounded-lg{
  border-radius: 0.5rem;
}
.rounded-xl{
  border-radius: 0.75rem;
}
.border{
  border-width: 1px;
}
.border-0{
  border-width: 0px;
}
.border-2{
  border-width: 2px;
}
.border-rule{
  border-width: var(--rule);
}
.border-b{
  border-bottom-width: 1px;
}
.border-b-rule{
  border-bottom-width: var(--rule);
}
.border-s-8{
  border-inline-start-width: 8px;
}
.border-t{
  border-top-width: 1px;
}
.border-t-rule{
  border-top-width: var(--rule);
}
.border-current{
  border-color: currentColor;
}
.border-ep-accent-fill{
  border-color: var(--accent-fill);
}
.border-ep-bad{
  border-color: var(--bad);
}
.border-ep-edge{
  border-color: var(--edge);
}
.border-ep-ink{
  border-color: var(--ink);
}
.border-ep-w-hair{
  border-color: var(--w-hair);
}
.border-ep-w-line{
  border-color: var(--w-line);
}
.border-s-ep-bad{
  border-inline-start-color: var(--bad);
}
.border-s-ep-ok{
  border-inline-start-color: var(--ok);
}
.border-s-ep-warn{
  border-inline-start-color: var(--warn);
}
.bg-\[var\(--accent-fill\)\]{
  background-color: var(--accent-fill);
}
.bg-ep-accent-fill{
  background-color: var(--accent-fill);
}
.bg-ep-ink{
  background-color: var(--ink);
}
.bg-ep-paper{
  background-color: var(--paper);
}
.bg-ep-surface{
  background-color: var(--surface);
}
.bg-ep-surface-hi{
  background-color: var(--surface-hi);
}
.fill-current{
  fill: currentColor;
}
.fill-ep-surface-hi{
  fill: var(--surface-hi);
}
.stroke-current{
  stroke: currentColor;
}
.p-0{
  padding: 0px;
}
.p-1{
  padding: 0.25rem;
}
.p-2{
  padding: 0.5rem;
}
.p-3{
  padding: 0.75rem;
}
.p-4{
  padding: 1rem;
}
.p-5{
  padding: 1.25rem;
}
.p-6{
  padding: 1.5rem;
}
.px-2{
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.px-2\.5{
  padding-left: 0.625rem;
  padding-right: 0.625rem;
}
.px-3{
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}
.px-4{
  padding-left: 1rem;
  padding-right: 1rem;
}
.px-5{
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}
.px-6{
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}
.py-0\.5{
  padding-top: 0.125rem;
  padding-bottom: 0.125rem;
}
.py-1{
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}
.py-16{
  padding-top: 4rem;
  padding-bottom: 4rem;
}
.py-2{
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
}
.py-2\.5{
  padding-top: 0.625rem;
  padding-bottom: 0.625rem;
}
.py-3{
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}
.py-4{
  padding-top: 1rem;
  padding-bottom: 1rem;
}
.py-\[clamp\(16px\2c 2\.6vw\2c 28px\)\]{
  padding-top: clamp(16px,2.6vw,28px);
  padding-bottom: clamp(16px,2.6vw,28px);
}
.pb-16{
  padding-bottom: 4rem;
}
.pb-2{
  padding-bottom: 0.5rem;
}
.pb-3{
  padding-bottom: 0.75rem;
}
.pb-5{
  padding-bottom: 1.25rem;
}
.pe-3{
  padding-inline-end: 0.75rem;
}
.pe-4{
  padding-inline-end: 1rem;
}
.pe-5{
  padding-inline-end: 1.25rem;
}
.pe-6{
  padding-inline-end: 1.5rem;
}
.pe-gut{
  padding-inline-end: var(--gut);
}
.ps-3{
  padding-inline-start: 0.75rem;
}
.ps-4{
  padding-inline-start: 1rem;
}
.ps-5{
  padding-inline-start: 1.25rem;
}
.ps-gut{
  padding-inline-start: var(--gut);
}
.pt-1{
  padding-top: 0.25rem;
}
.pt-10{
  padding-top: 2.5rem;
}
.pt-3{
  padding-top: 0.75rem;
}
.pt-4{
  padding-top: 1rem;
}
.pt-5{
  padding-top: 1.25rem;
}
.pt-6{
  padding-top: 1.5rem;
}
.pt-8{
  padding-top: 2rem;
}
.text-center{
  text-align: center;
}
.text-start{
  text-align: start;
}
.align-baseline{
  vertical-align: baseline;
}
.font-display{
  font-family: var(--font-display), Space Grotesk, sans-serif;
}
.font-ep-display{
  font-family: var(--ep-display);
}
.font-ep-ui{
  font-family: var(--ep-ui);
}
.font-sans{
  font-family: var(--font-sans), Inter, system-ui, sans-serif;
}
.text-\[13px\]{
  font-size: 13px;
}
.text-\[14px\]{
  font-size: 14px;
}
.text-\[15px\]{
  font-size: 15px;
}
.text-\[19px\]{
  font-size: 19px;
}
.text-\[28px\]{
  font-size: 28px;
}
.text-\[clamp\(20px\2c 2\.6vw\2c 38px\)\]{
  font-size: clamp(20px,2.6vw,38px);
}
.text-\[clamp\(26px\2c 3\.6vw\2c 58px\)\]{
  font-size: clamp(26px,3.6vw,58px);
}
.text-\[clamp\(28px\2c 4\.2vw\2c 64px\)\]{
  font-size: clamp(28px,4.2vw,64px);
}
.text-\[clamp\(28px\2c 4\.6vw\2c 68px\)\]{
  font-size: clamp(28px,4.6vw,68px);
}
.text-\[clamp\(30px\2c 4\.4vw\2c 76px\)\]{
  font-size: clamp(30px,4.4vw,76px);
}
.text-\[clamp\(30px\2c 5vw\2c 76px\)\]{
  font-size: clamp(30px,5vw,76px);
}
.text-\[clamp\(32px\2c 6vw\2c 92px\)\]{
  font-size: clamp(32px,6vw,92px);
}
.text-\[clamp\(38px\2c 6\.6vw\2c 116px\)\]{
  font-size: clamp(38px,6.6vw,116px);
}
.text-\[clamp\(38px\2c 7\.6vw\2c 104px\)\]{
  font-size: clamp(38px,7.6vw,104px);
}
.text-base{
  font-size: 1rem;
  line-height: 1.5rem;
}
.text-d0{
  font-size: var(--d0-size);
  line-height: var(--d0-lh);
  letter-spacing: var(--d0-track);
}
.text-d1{
  font-size: var(--d1-size);
  line-height: var(--d1-lh);
  letter-spacing: var(--d1-track);
}
.text-d2{
  font-size: var(--d2-size);
  line-height: var(--d2-lh);
  letter-spacing: var(--d2-track);
}
.text-d3{
  font-size: var(--d3-size);
  line-height: var(--d3-lh);
  letter-spacing: var(--d3-track);
}
.text-d4{
  font-size: var(--d4-size);
  line-height: var(--d4-lh);
  letter-spacing: var(--d4-track);
}
.text-lead{
  font-size: var(--lead-size);
  line-height: var(--lead-lh);
}
.text-lg{
  font-size: 1.125rem;
  line-height: 1.75rem;
}
.text-sm{
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.text-w-body{
  font-size: var(--w-body-size);
  line-height: var(--w-body-lh);
}
.text-w-label{
  font-size: var(--w-label-size);
  letter-spacing: var(--w-label-track);
}
.text-wh1{
  font-size: var(--wh1-size);
  line-height: 1;
}
.text-wh2{
  font-size: var(--wh2-size);
  line-height: 1.1;
}
.text-wh3{
  font-size: var(--wh3-size);
  line-height: 1.3;
}
.text-xl{
  font-size: 1.25rem;
  line-height: 1.75rem;
}
.text-xs{
  font-size: 0.75rem;
  line-height: 1rem;
}
.font-black{
  font-weight: 900;
}
.font-bold{
  font-weight: 700;
}
.font-extrabold{
  font-weight: 800;
}
.font-medium{
  font-weight: 500;
}
.font-normal{
  font-weight: 400;
}
.font-semibold{
  font-weight: 600;
}
.uppercase{
  text-transform: uppercase;
}
.lowercase{
  text-transform: lowercase;
}
.tabular-nums{
  --tw-numeric-spacing: tabular-nums;
  font-variant-numeric: var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);
}
.leading-\[0\.94\]{
  line-height: 0.94;
}
.leading-\[0\.96\]{
  line-height: 0.96;
}
.leading-\[0\.98\]{
  line-height: 0.98;
}
.leading-\[0\.9\]{
  line-height: 0.9;
}
.leading-\[1\.05\]{
  line-height: 1.05;
}
.leading-\[1\.12\]{
  line-height: 1.12;
}
.leading-relaxed{
  line-height: 1.625;
}
.tracking-\[-0\.025em\]{
  letter-spacing: -0.025em;
}
.tracking-\[-0\.028em\]{
  letter-spacing: -0.028em;
}
.tracking-\[-0\.02em\]{
  letter-spacing: -0.02em;
}
.tracking-\[-0\.035em\]{
  letter-spacing: -0.035em;
}
.tracking-\[-0\.03em\]{
  letter-spacing: -0.03em;
}
.tracking-\[-0\.045em\]{
  letter-spacing: -0.045em;
}
.tracking-\[-0\.04em\]{
  letter-spacing: -0.04em;
}
.tracking-normal{
  letter-spacing: 0em;
}
.text-\[var\(--on-accent\)\]{
  color: var(--on-accent);
}
.text-ep-accent{
  color: var(--accent);
}
.text-ep-bad{
  color: var(--bad);
}
.text-ep-ink{
  color: var(--ink);
}
.text-ep-on-accent{
  color: var(--on-accent);
}
.text-ep-paper{
  color: var(--paper);
}
.text-ep-w-faint{
  color: var(--w-faint);
}
.text-ep-w-mute{
  color: var(--w-mute);
}
.text-ep-warn{
  color: var(--warn);
}
.underline{
  text-decoration-line: underline;
}
.no-underline{
  text-decoration-line: none;
}
.underline-offset-4{
  text-underline-offset: 4px;
}
.antialiased{
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.accent-current{
  accent-color: currentColor;
}
.accent-ep-ink{
  accent-color: var(--ink);
}
.opacity-80{
  opacity: 0.8;
}
.shadow{
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.outline-none{
  outline: 2px solid transparent;
  outline-offset: 2px;
}
.outline{
  outline-style: solid;
}
.ring{
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
.blur{
  --tw-blur: blur(8px);
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.filter{
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.backdrop-filter{
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.transition{
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-colors{
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.transition-transform{
  transition-property: transform;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}
.duration-150{
  transition-duration: 150ms;
}
.\[overflow-wrap\:anywhere\]{
  overflow-wrap: anywhere;
}

/* Both, in that order. This is what decides whether the browser paints the
   surfaces IT owns — a native <select> menu, the number-input spinners, the
   scrollbars, the validation bubble — to match the theme the page is currently
   in. The console renders three selects and a number field on one screen, so
   getting this wrong is not a corner case. Declaring both also makes the
   browser follow the visitor's own setting, which is the same signal the
   palette follows. */
:root {
  color-scheme: light dark;
}

body {
  background-color: var(--paper);
  color: var(--ink);
}

/* Keep the editor action bar legible without an opaque white strip. */
.ep-publish-glass {
  box-sizing: border-box;
  max-width: 100%;
  background: var(--paper);
  border-top: 1px solid var(--w-line);
}

.ep-publish-status .ep-state::before { display: none; }
@supports (backdrop-filter: blur(16px)) {
  .ep-publish-glass {
    background: color-mix(in srgb, var(--paper) 88%, transparent);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
  }
}

::-moz-selection {
  background: var(--accent-fill);
  color: var(--on-accent);
}

::selection {
  background: var(--accent-fill);
  color: var(--on-accent);
}

/* Autofill is the one background a page cannot set directly: Chrome paints its
   own over the field and ignores background-color. The inset shadow is the
   documented way through — it is drawn INSIDE the field, on top of the browser
   fill, and the text colour has to be forced with -webkit-text-fill-color for
   the same reason. Without this, a saved name lands in a field that turns pale
   yellow-white on a navy form, which is exactly the moment an owner is asked to
   trust the page with their details. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  box-shadow: 0 0 0 1000px var(--surface-hi) inset;
  caret-color: var(--ink);
}

/* ---- kinetic engine (design-system §5) -----------------------------------
   JS writes --wght / --wdth as plain numbers on [data-kin]; they inherit down.
   Everything degrades to the static fallback if the axes are unavailable. */
.kin,
[data-kin] {
  font-variation-settings: "wght" var(--wght, 800), "wdth" var(--wdth, 112);
  font-weight: var(--wfall, 800);
}

/* No media query around the transition any more: the gate lives once on :root in
   tokens.css, where reduced motion shortens the duration instead of deleting the
   transition. A visitor who asked for less motion still gets told that the word
   under their finger is the one that responded.

   Weight only. Width was animated to 125 as well, and on a phone :hover fires on
   touch — so the word widened under the finger pressing it, moving the target
   mid-tap and reflowing the line around it. */
.kw {
  font-variation-settings: "wght" var(--wght, 800), "wdth" var(--wdth, 112);
  display: inline-block;
  transition: font-variation-settings var(--dur-field) var(--ease-out);
}
.kw:hover,
.kw:focus-visible {
  --wght: 900;
}

/* No variable axes — spend the difference on tracking instead of motion. */
@supports not (font-variation-settings: "wght" 700) {
  .kin,
  [data-kin],
  .kw {
    letter-spacing: -0.03em;
  }
}

/* ---- v2 focus: ring on a ring. The only pair that clears 3:1 on all seven
   fills, including yellow and lime, where a single accent ring fails.
   The deep band swaps the two rings — see .b-ink in poster.css.

   It applies to every focusable thing now, not to the two selectors that
   remembered to opt in. `.ep-focus` was a class somebody had to add by hand, so
   a keyboard visitor's ring appeared or vanished depending on which file the
   control happened to be written in. :where() keeps the specificity at zero, so
   a component can still override it deliberately. -------------------------- */
:where(
  a[href],
  button,
  input,
  select,
  textarea,
  summary,
  [tabindex]:not([tabindex="-1"])
):focus-visible {
  outline: var(--focus-width) solid var(--focus-outer);
  outline-offset: 2px;
  box-shadow: 0 0 0 calc(var(--focus-width) + 2px) var(--focus-inner);
}

/* The nav is fixed over the top of the page, so tabbing to a control near a
   section boundary scrolled it to exactly where the nav band covers it: focused,
   announced, and not on screen. */
:where(a[href], button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])) {
  scroll-margin-block-start: calc(var(--nav-h) + 8px);
}


/* Print, and it has to restate the whole light set rather than lean on it.
   `@media print` and `@media (prefers-color-scheme: dark)` carry the same
   specificity, so the only thing separating them is order — and a visitor
   reading in the dark theme who presses Ctrl+P would otherwise get near-white
   lettering on white paper, which is a blank sheet with a ghost on it.
   Backgrounds are dropped by the browser anyway; what is left is the document
   with its colour fields removed, which is the right thing to hand someone. */
@media print {
  :root {
    color-scheme: light;
    --paper: #ffffff;
    --surface: #ffffff;
    --surface-hi: #ffffff;
    --ink: #0f1a22;
    --text-mute: #354a55;
    --text-faint: #4f616b;
    --edge: #bcc7ce;
    --edge-strong: #66757e;
    --accent: #0c4674;
    --accent-fill: #0c4674;
    --accent-deep: #0c4674;
    --on-accent: #ffffff;
    --accent-2: #6b4f10;
    --signal: #9c1c17;
    --fill-accent: #d3e5f4;
    --fill-person: #efe3ca;
    --fill-info: #dcebe3;
    --w-bg: #ffffff;
    --w-panel: #ffffff;
    --w-line: #66757e;
    --w-hair: rgba(15, 26, 34, 0.2);
    --w-mute: #354a55;
    --w-faint: #4f616b;
    --ok: #1a5c38;
    --warn: #684b0f;
    --bad: #911711;
    --grad-cta: none;
    --grad-hero: none;
  }

  .ep-nav,
  .ep-carousel-arrow,
  .ep-carousel-dot {
    display: none;
  }
}

/* Forced colours — Windows High Contrast and friends. Every other paint in this
   system is a background-color, a color, a border-color or a box-shadow, and
   the engine substitutes all four with the user's own system colours. The two
   gradients are background-IMAGE, which it does not reliably replace, so they
   are removed here rather than left to survive as the only un-themed surfaces
   on a page the visitor asked to re-colour entirely. */
@media (forced-colors: active) {
  .b-hero,
  .ep-vs-cta,
  .ep-bar {
    background-image: none;
    background-color: ButtonFace;
    color: ButtonText;
    border: 1px solid ButtonText;
  }
}
.first\:mt-0:first-child{
  margin-top: 0px;
}
.last\:border-b-0:last-child{
  border-bottom-width: 0px;
}
.hover\:border-ep-ink:hover{
  border-color: var(--ink);
}
.hover\:bg-ep-surface-hi:hover{
  background-color: var(--surface-hi);
}
.focus-visible\:outline:focus-visible{
  outline-style: solid;
}
.focus-visible\:outline-2:focus-visible{
  outline-width: 2px;
}
.focus-visible\:outline-offset-2:focus-visible{
  outline-offset: 2px;
}
.disabled\:cursor-not-allowed:disabled{
  cursor: not-allowed;
}
.disabled\:cursor-wait:disabled{
  cursor: wait;
}
.disabled\:opacity-50:disabled{
  opacity: 0.5;
}
.disabled\:opacity-60:disabled{
  opacity: 0.6;
}
.disabled\:opacity-70:disabled{
  opacity: 0.7;
}
.group[open] .group-open\:rotate-45{
  --tw-rotate: 45deg;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.peer:checked ~ .peer-checked\:bg-ep-ink{
  background-color: var(--ink);
}
.peer:checked ~ .peer-checked\:text-ep-paper{
  color: var(--paper);
}
.peer:focus-visible ~ .peer-focus-visible\:outline{
  outline-style: solid;
}
.peer:focus-visible ~ .peer-focus-visible\:outline-2{
  outline-width: 2px;
}
.peer:focus-visible ~ .peer-focus-visible\:outline-offset-2{
  outline-offset: 2px;
}
.peer:disabled ~ .peer-disabled\:opacity-50{
  opacity: 0.5;
}
.aria-disabled\:opacity-70[aria-disabled="true"]{
  opacity: 0.7;
}
@media (min-width: 640px){

  .sm\:col-span-2{
    grid-column: span 2 / span 2;
  }

  .sm\:mt-10{
    margin-top: 2.5rem;
  }

  .sm\:mt-12{
    margin-top: 3rem;
  }

  .sm\:mt-16{
    margin-top: 4rem;
  }

  .sm\:block{
    display: block;
  }

  .sm\:flex{
    display: flex;
  }

  .sm\:inline-flex{
    display: inline-flex;
  }

  .sm\:hidden{
    display: none;
  }

  .sm\:h-11{
    height: 2.75rem;
  }

  .sm\:h-7{
    height: 1.75rem;
  }

  .sm\:w-14{
    width: 3.5rem;
  }

  .sm\:w-\[88px\]{
    width: 88px;
  }

  .sm\:grid-cols-2{
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sm\:gap-3{
    gap: 0.75rem;
  }

  .sm\:gap-x-5{
    -moz-column-gap: 1.25rem;
         column-gap: 1.25rem;
  }

  .sm\:gap-x-6{
    -moz-column-gap: 1.5rem;
         column-gap: 1.5rem;
  }

  .sm\:p-5{
    padding: 1.25rem;
  }

  .sm\:pe-4{
    padding-inline-end: 1rem;
  }

  .sm\:ps-12{
    padding-inline-start: 3rem;
  }

  .sm\:ps-4{
    padding-inline-start: 1rem;
  }
}
@media (min-width: 1024px){

  .lg\:sticky{
    position: sticky;
  }

  .lg\:inset-x-auto{
    left: auto;
    right: auto;
  }

  .lg\:bottom-0{
    bottom: 0px;
  }

  .lg\:bottom-full{
    bottom: 100%;
  }

  .lg\:top-auto{
    top: auto;
  }

  .lg\:mb-2{
    margin-bottom: 0.5rem;
  }

  .lg\:mt-0{
    margin-top: 0px;
  }

  .lg\:block{
    display: block;
  }

  .lg\:w-\[22rem\]{
    width: 22rem;
  }

  .lg\:grid-cols-2{
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .lg\:grid-cols-\[10ch_minmax\(0\2c 16ch\)\]{
    grid-template-columns: 10ch minmax(0,16ch);
  }

  .lg\:grid-cols-\[minmax\(0\2c 16ch\)_minmax\(0\2c 16ch\)\]{
    grid-template-columns: minmax(0,16ch) minmax(0,16ch);
  }

  .lg\:flex-row{
    flex-direction: row;
  }

  .lg\:items-center{
    align-items: center;
  }

  .lg\:gap-8{
    gap: 2rem;
  }

  .lg\:rounded-\[var\(--r-panel\)\]{
    border-radius: var(--r-panel);
  }

  .lg\:\!pb-16{
    padding-bottom: 4rem !important;
  }
}
@media (min-width: 1280px){

  .xl\:grid-cols-4{
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{
  display: none;
}

