/* O2 Design Studio — site styles.
   One file, hand-written. Tokens, base, layout, components, pages, preferences.

   The look: a cool paper canvas, deep ink type, hairlines instead of borders,
   and cobalt used as an accent rather than a fill. Motion follows the
   apple-design skill: feedback on the press, movement from the current value,
   no bounce unless a gesture carried momentum, and a quieter equivalent for
   every reduced-motion, reduced-transparency and higher-contrast preference. */

/* Thai only. Latin stays on the system font. The system Thai face is different
   on every platform, and on Apple devices it is a traditional looped design that
   sits awkwardly beside the Latin; Anuphan is a loopless Thai face that matches
   it. One 19 KB file, used only for Thai characters. Licence: src/fonts/OFL-Anuphan.txt */
@font-face { font-family: "Anuphan"; font-style: normal; font-weight: 100 700; font-display: swap; src: url(/assets/fonts/anuphan-thai.d1ad2c518e.woff2) format("woff2"); unicode-range: U+0E01-0E5B, U+200C-200D, U+25CC; }

:root {
  --canvas: #F6F8FC;
  --surface: #FFFFFF;
  --sunken: #EEF1F6;
  --ink: #111722;
  --ink-2: #4B5668;
  --ink-3: #5F6A7D;
  --ink-4: #7F889A;            /* large display text (3.4:1 on the canvas) and decoration only */
  --accent: #245BFF;
  --accent-press: #1B49D6;
  --accent-soft: #EAF0FF;
  --hair: rgba(17, 23, 34, .08);
  --hair-2: rgba(17, 23, 34, .14);
  --dark: #101522;
  --dark-2: #161C2B;
  --on-dark: #F3F5F9;
  --on-dark-2: #A9B4C6;
  --on-dark-accent: #9DB8FF;
  --hair-dark: rgba(255, 255, 255, .12);
  --ok: #0E7A4B; --ok-soft: #E6F5EE;
  --warn: #7E5300; --warn-soft: #FFF4DB;
  --err: #B3261E; --err-soft: #FDECEA;

  /* Colours that only exist so the dark theme can change them. */
  --on-ink: #FFFFFF;            /* text on a control filled with --ink */
  --ink-hover: #000000;         /* that control, hovered */
  --on-accent: #FFFFFF;         /* text on --accent or --ok */
  --canvas-rgb: 246, 248, 252;  /* the page colour, for translucent bars */
  --ink-rgb: 17, 23, 34;        /* faint tints of the text colour */
  --shade-rgb: 17, 23, 34;      /* shadows */
  --glow-rgb: 36, 91, 255;      /* the soft light behind the hero */
  --focus-halo: rgba(36, 91, 255, .16);
  --scrim: rgba(16, 21, 34, .3);
  --tray-bg: rgba(16, 21, 34, .84);
  --select: #D5E0FF;
  --warn-dot: #D99A1C;
  --bar: #D3DEFF;               /* chart bars in the dashboard preview */
  --alert-err: #7A1A14; --alert-info: #1B2C5C; --alert-warn: #563700;
  --sun: #B26F00; --sun-soft: #FFF1D0;    /* the theme switch, light side */

  --r-s: 10px; --r-m: 14px; --r-l: 20px; --r-xl: 28px; --pill: 999px;
  --shadow-card: 0 0 0 1px var(--hair), 0 1px 2px rgba(17, 23, 34, .03), 0 12px 32px -16px rgba(17, 23, 34, .12);
  --shadow-lift: 0 0 0 1px var(--hair), 0 2px 4px rgba(17, 23, 34, .04), 0 22px 48px -18px rgba(17, 23, 34, .2);
  --shadow-float: 0 0 0 1px var(--hair), 0 2px 6px rgba(17, 23, 34, .04), 0 40px 80px -28px rgba(17, 23, 34, .28);
  --gutter: clamp(20px, 4.4vw, 56px);
  --band: clamp(52px, 6.2vw, 92px);
  --nav-h: 60px;

  --ease: cubic-bezier(.2, .8, .2, 1);
  --t-press: 100ms;
  --t-fast: 180ms;
  --t-med: 320ms;
  --t-slow: 640ms;

  --font: "Anuphan", -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", system-ui, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Noto Sans Thai", "Leelawadee UI", Thonburi, sans-serif;
  --lh-tight: 1.05;
  --lh-head: 1.12;
  --lh-body: 1.52;
  --trk-display: -.036em;
  --trk-head: -.026em;
  --trk-sub: -.014em;
}

/* ---- dark theme ---------------------------------------------------------------
   Chosen with the switch in the top bar (site.js) and remembered on the device.
   Only tokens change here; components are written against the tokens. The dark
   bands (--dark) sit a step above the page so they still read as bands. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --canvas: #0C1019;
  --surface: #161C2A;
  --sunken: #1E2536;
  --ink: #F2F4F8;
  --ink-2: #C4CCDA;
  --ink-3: #A2ADC1;
  --ink-4: #7C879C;
  --accent: #8FADFF;
  --accent-press: #B3C7FF;
  --accent-soft: #1A2644;
  --hair: rgba(255, 255, 255, .09);
  --hair-2: rgba(255, 255, 255, .17);
  --dark: #131927;
  --dark-2: #1B2233;
  --ok: #62D2A2; --ok-soft: #10281D;
  --warn: #EDBE63; --warn-soft: #2C2410;
  --err: #FF9C92; --err-soft: #381513;

  --shadow-card: 0 0 0 1px var(--hair), 0 12px 32px -16px rgba(0, 0, 0, .6);
  --shadow-lift: 0 0 0 1px var(--hair), 0 22px 48px -18px rgba(0, 0, 0, .7);
  --shadow-float: 0 0 0 1px var(--hair-2), 0 40px 80px -28px rgba(0, 0, 0, .8);

  --on-ink: #0F1420;
  --ink-hover: #FFFFFF;
  --on-accent: #0B1226;
  --canvas-rgb: 12, 16, 25;
  --ink-rgb: 255, 255, 255;
  --shade-rgb: 0, 0, 0;
  --glow-rgb: 84, 128, 255;
  --focus-halo: rgba(143, 173, 255, .3);
  --scrim: rgba(0, 0, 0, .55);
  --tray-bg: rgba(30, 37, 54, .9);
  --select: #2C417F;
  --warn-dot: #EDBE63;
  --bar: rgba(143, 173, 255, .3);
  --alert-err: #FFC9C3; --alert-info: #C9D8FF; --alert-warn: #F6DCA2;
}
:root[data-theme="dark"] .tray { box-shadow: 0 0 0 1px var(--hair-2), 0 22px 48px -18px rgba(0, 0, 0, .7); }
/* Thai has tall vowel and tone marks: open the leading, and never tighten the tracking. */
:root:lang(th) {
  --lh-tight: 1.26; --lh-head: 1.34; --lh-body: 1.7;
  --trk-display: 0em; --trk-head: 0em; --trk-sub: 0em;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-top: calc(var(--nav-h) + 16px); }
body {
  margin: 0; background: var(--canvas); color: var(--ink);
  font: 400 1.0625rem/var(--lh-body) var(--font);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
  font-optical-sizing: auto; overflow-wrap: break-word;
}
h1, h2, h3, h4, p, ul, ol, figure, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
main:focus { outline: none; }
::selection { background: var(--select); }

/* Thai borrowed words the browser's dictionary would cut (src/lib/html.mjs wraps them on Thai pages).
   o2-k: no line break inside the word. o2-w: a place to break before it (w-a) or after it (w-b), where
   it touches another Thai letter, so the dictionary reads the words beside it correctly. Neither makes
   a box. o2-t, around the run of text they stand in, is an ordinary inline element and needs no rule:
   it keeps that run one item where its parent lays its content out as a row or a grid. */
o2-w, o2-k { display: contents; }
o2-k { white-space: nowrap; }
o2-w.w-a::before, o2-w.w-b::after { content: "\200B"; }
.vh { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.skip { position: fixed; left: 12px; top: -80px; z-index: 200; background: var(--ink); color: var(--on-ink); padding: 12px 16px; border-radius: var(--r-s); text-decoration: none; }
.skip:focus { top: 12px; }
.wrap { width: 100%; max-width: calc(1200px + var(--gutter) * 2); margin-inline: auto; padding-inline: var(--gutter); }

/* ---- type ---------------------------------------------------------------- */
.display { font-size: clamp(2.5rem, 1.25rem + 3.6vw, 4.25rem); line-height: var(--lh-tight); letter-spacing: var(--trk-display); font-weight: 600; }
.display span { display: block; text-wrap: balance; }
:lang(th) .display { font-size: clamp(2.125rem, 1.1rem + 3vw, 3.5rem); }
:lang(th) .h1 { font-size: clamp(2rem, 1.3rem + 2.5vw, 3.25rem); }
/* The second half of a display heading, quieter than the first. --ink-3 on light (about 5:1; it was --ink-4, 3.4:1,
   which the audit of 17 October 2026 found too faint for the sentence that carries the offer); --ink-4 on dark is
   already over 5:1, and anything lighter would read as the first half. */
.display__2 { color: var(--ink-3); }
:root[data-theme="dark"] .display__2 { color: var(--ink-4); }
.h1 { font-size: clamp(2.25rem, 1.4rem + 2.9vw, 3.75rem); line-height: var(--lh-tight); letter-spacing: var(--trk-display); font-weight: 600; text-wrap: balance; }
.h2 { font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem); line-height: var(--lh-head); letter-spacing: var(--trk-head); font-weight: 600; text-wrap: balance; }
.h3 { font-size: 1.1875rem; line-height: 1.3; letter-spacing: var(--trk-sub); font-weight: 600; }
:lang(th) .h3 { line-height: 1.5; }
.lead { font-size: clamp(1.0625rem, 1rem + .5vw, 1.3125rem); line-height: 1.42; color: var(--ink-2); letter-spacing: var(--trk-sub); text-wrap: pretty; }
:lang(th) .lead { line-height: 1.68; }
.small { font-size: .875rem; line-height: 1.5; color: var(--ink-3); }
:lang(th) .small { line-height: 1.68; }
.eyebrow { display: inline-flex; align-items: center; gap: 10px; font-size: .875rem; line-height: 1.4; font-weight: 500; color: var(--ink-3); }
.eyebrow::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
.link { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); font-weight: 550; text-decoration: none; background: none; border: 0; padding: 0; min-height: 28px; }
.link .i { color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.i { width: 16px; height: 16px; flex: none; }

/* The spark beside "Find my solution". At rest it is the text colour. When its
   button or link is hovered or focused it turns a quarter, and a band of colour
   runs through it for as long as the pointer stays. The colour layer is the
   same star, cut from a moving gradient two cycles wide, so the loop has no seam. */
.spark { position: relative; display: inline-grid; place-items: center; width: 16px; height: 16px; flex: none; transition: transform 520ms var(--ease), filter var(--t-med) ease; }
.spark .i { transition: opacity var(--t-fast) ease; }
.spark::after {
  content: ""; position: absolute; inset: -1px; opacity: 0; transition: opacity var(--t-fast) ease;
  background: linear-gradient(90deg, #2F6BFF, #8B5CF6, #EC4899, #F59E0B, #2F6BFF, #8B5CF6, #EC4899, #F59E0B, #2F6BFF) 0 50% / 200% 100%;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1.8 9.5 6.5 14.2 8 9.5 9.5 8 14.2 6.5 9.5 1.8 8 6.5 6.5Z'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1.8 9.5 6.5 14.2 8 9.5 9.5 8 14.2 6.5 9.5 1.8 8 6.5 6.5Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
:is(.btn, .link):not([disabled]):focus-visible .spark { transform: rotate(90deg) scale(1.2); filter: drop-shadow(0 0 5px rgba(139, 92, 246, .5)); }
:is(.btn, .link):not([disabled]):focus-visible .spark .i { opacity: 0; }
:is(.btn, .link):not([disabled]):focus-visible .spark::after { opacity: 1; animation: spark-flow 1.8s linear infinite; }
@keyframes spark-flow { to { background-position: 100% 50%; } }

/* ---- buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 24px; border-radius: var(--pill); border: 0;
  font-weight: 550; font-size: 1rem; line-height: 1.2; letter-spacing: var(--trk-sub); text-decoration: none; white-space: nowrap;
  transition: transform var(--t-press) ease-out, background-color var(--t-fast) ease, box-shadow var(--t-fast) ease, color var(--t-fast) ease;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
.btn:active { transform: scale(.97); }
.btn--s { min-height: 40px; padding: 0 17px; font-size: .9375rem; }
.btn--primary { background: var(--ink); color: var(--on-ink); }
.btn--ghost { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--hair-2); }
.btn--quiet { background: transparent; color: var(--ink-2); padding-inline: 14px; box-shadow: inset 0 0 0 1px var(--hair); }
.btn--on-dark { background: rgba(255, 255, 255, .07); color: var(--on-dark); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2); }
.band--dark .btn--primary, .tray .btn--primary { background: #fff; color: #111722; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
.btn .i-check { display: none; }
.js-add[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-press); box-shadow: none; }
.js-add[aria-pressed="true"] .i-plus { display: none; }
.js-add[aria-pressed="true"] .i-check { display: block; }
.actions { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: center; }

/* ---- nav: a translucent layer the page scrolls under ---------------------- */
.nav { position: fixed; inset: 0 0 auto 0; z-index: 100; background: rgba(var(--canvas-rgb), .72); -webkit-backdrop-filter: saturate(180%) blur(22px); backdrop-filter: saturate(180%) blur(22px); transition: box-shadow var(--t-med) ease, background-color var(--t-med) ease; }
.nav--scrolled, .nav--open { background: rgba(var(--canvas-rgb), .86); box-shadow: 0 1px 0 var(--hair); }
.nav__bar { height: var(--nav-h); display: flex; align-items: center; gap: 24px; }
.nav__logo { display: inline-flex; align-items: center; flex: none; min-height: 44px; margin-right: 4px; color: var(--ink); }
/* Under 360px the bar cannot hold the mark, the theme switch, the whole label and the menu button (at 340 it pushes the
   menu button into the margin): the button says "Contact us" instead, a label of its own rather than the first word
   of the long one. Nothing is squeezed. */
.nav__cta-short { display: none; }
@media (max-width: 22.49em) { .nav__cta-full { display: none; } .nav__cta-short { display: inline; } }
.mark { width: 42px; height: 34px; }
.nav__links { display: none; flex: 1; min-width: 0; align-items: center; gap: 2px; margin-right: auto; }
.nav__links > a { position: relative; display: inline-flex; align-items: center; min-height: 40px; padding: 0 12px; font-size: .9375rem; color: var(--ink-2); text-decoration: none; transition: color var(--t-fast) ease; }
.nav__links > a::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 7px; height: 1.5px; border-radius: 1px; background: var(--ink); transform: scaleX(0); transform-origin: left; transition: transform var(--t-med) var(--ease); }
.nav__links > a[aria-current] { color: var(--ink); font-weight: 550; }
.nav__links > a[aria-current]::after { transform: scaleX(1); }
.nav__end { display: flex; align-items: center; gap: 12px; margin-left: auto; }
@media (max-width: 379px) { .nav__end { gap: 8px; } .nav__bar { gap: 12px; } }
.nav__toggle { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 0; background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair-2); transition: transform var(--t-press) ease-out; }
.nav__toggle:active { transform: scale(.95); }
/* Light / dark switch: a sun while the page is light, a crescent once it is dark. */
.theme { position: relative; display: inline-grid; place-items: center; width: 40px; height: 40px; flex: none; border-radius: 50%; border: 0; background: var(--sun-soft); color: var(--sun); box-shadow: inset 0 0 0 1px rgba(var(--ink-rgb), .06); transition: transform var(--t-press) ease-out, background-color var(--t-med) ease, color var(--t-med) ease; }
.theme:active { transform: scale(.94); }
.theme svg { grid-area: 1 / 1; width: 20px; height: 20px; transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease); }
.theme .i-moon { opacity: 0; transform: rotate(-60deg) scale(.6); }
:root[data-theme="dark"] .theme { background: var(--accent-soft); color: var(--accent-press); }
:root[data-theme="dark"] .theme .i-sun { opacity: 0; transform: rotate(60deg) scale(.6); }
:root[data-theme="dark"] .theme .i-moon { opacity: 1; transform: none; }
.nav__toggle-close, .nav--open .nav__toggle-open { display: none; }
.nav--open .nav__toggle-close { display: block; }
.lang { display: inline-flex; align-items: center; }
.lang a { display: inline-flex; align-items: center; min-height: 40px; padding: 0 8px; font-size: .875rem; font-weight: 500; color: var(--ink-3); text-decoration: none; line-height: 1; transition: color var(--t-fast) ease; }
.lang a + a { position: relative; }
.lang a + a::before { content: ""; position: absolute; left: -.5px; top: 50%; height: 12px; margin-top: -6px; border-left: 1px solid var(--hair-2); }
.lang a[aria-current="true"] { color: var(--ink); font-weight: 600; }
.lang--bar { display: none; }

/* Language and appearance, one menu in the bar (the owner, 19 October 2026: "make this a drop down menu in order to make
   the top bar less cluttered"). A details element: it opens and closes without a script; src/js/site.js closes it on a
   press outside and on Escape. It drops from where it is pressed. */
.prefs { position: relative; flex: none; }
.prefs > summary { list-style: none; }
.prefs > summary::-webkit-details-marker { display: none; }
.prefs__btn { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 0 10px 0 11px; border-radius: 999px; background: var(--surface); color: var(--ink-2); font-size: .875rem; font-weight: 550; box-shadow: inset 0 0 0 1px var(--hair-2); cursor: pointer; user-select: none; transition: color var(--t-fast) ease, box-shadow var(--t-fast) ease, transform 120ms var(--ease); }
.prefs__btn:hover, .prefs[open] .prefs__btn { color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink-3); }
.prefs__btn:active { transform: scale(.97); }
.prefs__btn .i-globe { width: 17px; height: 17px; }
.prefs__btn .nav__chev { width: 14px; height: 14px; transition: transform var(--t-med) var(--ease); }
.prefs[open] .prefs__btn .nav__chev { transform: rotate(180deg); }
.prefs__panel { position: absolute; top: calc(100% + 8px); right: 0; z-index: 40; display: grid; gap: 2px; width: 232px; padding: 8px; border-radius: 18px; background: var(--surface); box-shadow: var(--shadow-float); transform-origin: top right; }
.prefs[open] .prefs__panel { animation: prefs-in 180ms var(--ease) both; }
@keyframes prefs-in { from { opacity: 0; transform: translateY(-4px) scale(.98); } }
.prefs__h { margin: 6px 10px 2px; font-size: .75rem; font-weight: 600; color: var(--ink-3); }
.prefs__langs { display: grid; }
.prefs__langs a { justify-content: space-between; min-height: 40px; padding: 0 10px; border-radius: 10px; font-size: .9375rem; color: var(--ink); }
.prefs__langs a + a::before { content: none; }
.prefs__langs .i-check { width: 16px; height: 16px; color: var(--accent); opacity: 0; }
.prefs__langs a[aria-current="true"] .i-check { opacity: 1; }
.theme.prefs__theme { display: flex; justify-content: flex-start; gap: 10px; width: 100%; height: auto; min-height: 40px; padding: 0 10px; border-radius: 10px; background: transparent; color: var(--ink); box-shadow: none; font: inherit; font-size: .9375rem; text-align: start; cursor: pointer; }
.theme.prefs__theme svg { width: 18px; height: 18px; color: var(--sun); }
.theme.prefs__theme .i-moon, :root[data-theme="dark"] .theme.prefs__theme .i-sun { display: none; }
:root[data-theme="dark"] .theme.prefs__theme .i-moon { display: block; color: var(--accent-press); }
.theme__to-light, :root[data-theme="dark"] .theme__to-dark { display: none; }
:root[data-theme="dark"] .theme__to-light { display: inline; }
@media (hover: hover) and (pointer: fine) { .prefs__langs a:hover, .theme.prefs__theme:hover { background: var(--sunken); } }
/* On a phone the button sits mid-bar, so the panel is placed against the screen's right edge rather than the button's. */
@media (max-width: 66.99em) { .prefs__panel { position: fixed; top: calc(var(--nav-h) + 6px); right: 12px; width: min(232px, calc(100vw - 24px)); } }
@media (max-width: 399px) { .prefs__now { display: none; } .prefs__btn { padding: 0 9px; } }
@media (prefers-reduced-motion: reduce) { .prefs[open] .prefs__panel { animation: none; } .prefs__btn .nav__chev { transition: none; } }
@media (prefers-contrast: more) { .prefs__panel { box-shadow: 0 0 0 1px var(--hair-2); } }

.sheet { background: rgba(var(--canvas-rgb), .97); border-top: 1px solid var(--hair); max-height: calc(100dvh - var(--nav-h)); overflow-y: auto; overscroll-behavior: contain; opacity: 0; transform: translateY(-10px); transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease); }
.sheet--in { opacity: 1; transform: none; }
.sheet__in { display: grid; padding-block: 8px calc(22px + env(safe-area-inset-bottom)); }
.sheet__link { display: flex; align-items: center; min-height: 58px; font-size: 1.375rem; font-weight: 550; letter-spacing: var(--trk-head); text-decoration: none; border-bottom: 1px solid var(--hair); }
.sheet__link[aria-current], .sheet__link.is-current { color: var(--accent); }
/* A section with pages under it unfolds in the phone menu; its own page is the first link inside. */
.sheet__group > summary { justify-content: space-between; list-style: none; cursor: pointer; }
.sheet__group > summary::-webkit-details-marker { display: none; }
.sheet__group .nav__chev { width: 18px; height: 18px; color: var(--ink-3); transition: transform var(--t-fast) var(--ease); }
.sheet__group[open] .nav__chev { transform: rotate(180deg); }
.sheet__sub { display: grid; padding: 4px 0 10px; border-bottom: 1px solid var(--hair); }
.sheet__group[open] > summary { border-bottom-color: transparent; }
.sheet__sub a { display: flex; align-items: center; min-height: 46px; font-size: 1.0625rem; color: var(--ink-2); text-decoration: none; }
.sheet__sub a[aria-current] { color: var(--accent); font-weight: 550; }
/* The bar's panels: the pages of a section, under its entry. Shown only while the bar shows its links. */
.nav__bar { position: relative; }
.nav__dd { gap: 4px; }
.nav__chev { width: 13px; height: 13px; color: var(--ink-3); transition: transform var(--t-fast) var(--ease); }
.nav__dd[aria-expanded="true"] { color: var(--ink); }
.nav__dd[aria-expanded="true"] .nav__chev { transform: rotate(180deg); }
.npanel { position: absolute; top: calc(100% - 6px); left: 0; z-index: 2; width: min(21rem, calc(100vw - var(--gutter) * 2)); padding: 8px; border-radius: var(--r-l); background: var(--surface); box-shadow: var(--shadow-lift); opacity: 0; transform: translateY(-6px) scale(.98); transform-origin: 24px 0; transition: opacity 160ms ease, transform 220ms var(--ease); }
.npanel--notes { width: min(40rem, calc(100vw - var(--gutter) * 2)); }
.npanel--in { opacity: 1; transform: none; }
.npanel__list { display: grid; gap: 2px; }
.npanel--notes .npanel__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.npanel__list a { display: grid; gap: 2px; align-content: center; min-height: 44px; padding: 9px 12px; border-radius: var(--r-s); color: var(--ink); text-decoration: none; }
.npanel__list b { font-size: .9375rem; font-weight: 550; }
.npanel__list span { font-size: .8125rem; line-height: 1.45; color: var(--ink-3); }
.npanel__list a[aria-current] b { color: var(--accent); }
.npanel__list a:focus-visible, .npanel__list a:active { background: var(--canvas); }
.npanel__all { display: flex; margin: 6px 4px 2px; padding: 10px 8px 6px; border-top: 1px solid var(--hair); font-size: .875rem; }
.nav--fold .npanel { display: none; }
@media (max-width: 67.49em) { .npanel { display: none; } }
@media (prefers-reduced-motion: reduce) { .npanel { transform: none; transition: opacity 120ms ease; } }
.sheet__foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding-top: 22px; }
.scrim { position: fixed; inset: 0; z-index: 90; background: var(--scrim); opacity: 0; transition: opacity var(--t-med) ease; }
.scrim--in { opacity: 1; }

/* The links are shown when there is room for them, and room is measured in the reader's own text size:
   67.5em is 1080px at the usual 16px, and wider in step with a larger default. While they are shown the
   bar may grow by the same measure (75rem is the page's 1200px at 16px), so larger text has the width
   it needs on a wide screen; with the menu button it keeps the page's own width and lines up with the
   content. Where the links still do not fit, the page's script folds the header to the menu button
   (.nav--fold, src/js/site.js). */
@media (min-width: 67.5em) {
  .nav:not(.nav--fold) .nav__bar { max-width: calc(75rem + var(--gutter) * 2); }
  .nav:not(.nav--fold) .nav__links { display: flex; }
  .nav:not(.nav--fold) .lang--bar { display: inline-flex; }
  .nav:not(.nav--fold) :is(.nav__toggle, .sheet), .nav:not(.nav--fold) + .scrim { display: none !important; }
}
@media (max-width: 420px) {
  .nav__cta { padding: 0 14px; font-size: .875rem; }
  .nav__bar { gap: 8px; }
  .nav__end { gap: 8px; }
}
/* A phone with the text enlarged. A window under 20em wide is one: at the usual 16px that is 320px, and no
   phone is narrower. There a button's words may take a second line instead of running off the side; and
   under 17.5em the header's button no longer fits beside the logo and the menu button, so it gives way
   (the menu has Contact in it). */
@media (max-width: 19.99em) {
  .btn { white-space: normal; padding-block: 10px; text-align: center; }
  .pd-whole { white-space: normal; }
}
@media (max-width: 17.49em) { .nav__cta { display: none; } }

main { padding-top: var(--nav-h); }

/* ---- bands and section heads --------------------------------------------- */
.band { padding-block: var(--band); }
.band--flush { padding-top: 0; }
.band--tint { background: var(--surface); }
.band--dark { background: var(--dark); color: var(--on-dark); }
.band--dark .lead, .band--dark .small { color: var(--on-dark-2); }
.band--dark .link { color: var(--on-dark); }
.band--dark .link .i { color: var(--on-dark-accent); }
.band--dark :focus-visible { outline-color: var(--on-dark-accent); }
.head { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: 12px 40px; margin-bottom: clamp(28px, 3.6vw, 48px); }
.head .h2 { max-width: 24ch; }
.head__side { max-width: 40ch; color: var(--ink-2); }
.band--dark .head__side { color: var(--on-dark-2); }
.intro { padding-block: clamp(36px, 5.4vw, 84px) clamp(28px, 3.6vw, 52px); }
.intro .h1 { max-width: 18ch; margin-top: 14px; }
.intro .eyebrow + .h1 { margin-top: 16px; }
.intro__lead { max-width: 52ch; margin-top: 20px; }
.intro .actions { margin-top: 28px; }

.crumbs { margin-bottom: 14px; }
.crumbs ol { display: flex; flex-wrap: wrap; gap: 8px; font-size: .875rem; color: var(--ink-3); }
.crumbs li + li::before { content: "/"; margin-right: 8px; color: var(--hair-2); }
.crumbs li { display: inline-flex; align-items: center; min-height: 32px; }
.crumbs a { display: inline-flex; align-items: center; min-height: 32px; text-decoration: none; }

.ticks { display: grid; gap: 10px; }
.ticks li { position: relative; padding-left: 28px; }
.ticks li::before { content: ""; position: absolute; left: 3px; top: .5em; width: 13px; height: 7px; border-left: 1.75px solid var(--accent); border-bottom: 1.75px solid var(--accent); transform: rotate(-45deg) scale(.85); transform-origin: left bottom; }
:lang(th) .ticks li::before { top: .7em; }

.tags { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }
.tag { display: inline-flex; align-items: center; gap: 7px; font-size: .8125rem; font-weight: 550; line-height: 1.2; color: var(--ink-2); }
.tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); flex: none; }
.tag--client { color: var(--accent-press); } .tag--client::before { background: var(--accent); }
.tag--live { color: var(--ok); } .tag--live::before { background: var(--ok); }
.tag--progress { color: var(--warn); } .tag--progress::before { background: var(--warn-dot); }
/* A commissioned site that is with its client for review, and a note beside a name ("New", "Needs assessment"):
   the same quiet amber, under names of their own, because "progress" is a kind of project. */
.tag--review, .tag--note { color: var(--warn); } .tag--review::before, .tag--note::before { background: var(--warn-dot); }
.tag--concept { color: var(--ink-3); }

/* ---- hero ---------------------------------------------------------------- */
.hero { position: relative; overflow: clip; padding-block: clamp(28px, 4.4vw, 68px) clamp(16px, 2.4vw, 32px); }
.hero::before { content: ""; position: absolute; inset: -20% -10% 0 30%; pointer-events: none; background: radial-gradient(46% 44% at 62% 38%, rgba(var(--glow-rgb), .13), transparent 70%), radial-gradient(34% 32% at 30% 78%, rgba(var(--glow-rgb), .06), transparent 70%); }
.hero__in { position: relative; z-index: 1; display: grid; gap: clamp(32px, 4.4vw, 64px); align-items: center; }
.hero__copy .display { margin-top: 20px; }
.hero__copy .lead { margin-top: 24px; max-width: 32ch; }
.hero__copy .actions { margin-top: 32px; }
.hero__scene { position: relative; min-width: 0; }
/* The home page's opening: one example, large enough to read. It shows the first screen of the example
   for the kind of business in mind; the choice itself is made in the section below, and this follows it. */
.hero--alone .hero__in { grid-template-columns: minmax(0, 1fr); }
.hero__copy .lead { max-width: 36ch; }
/* A whole sentence as the headline: a size down from the two-line display, so it stays three lines beside the scene. */
.hero__copy .display { font-size: clamp(2.25rem, 1.2rem + 2.7vw, 3.5rem); }
:lang(th) .hero__copy .display { font-size: clamp(2.125rem, 1.2rem + 2.3vw, 3.125rem); }
.scene { position: relative; z-index: 1; display: block; }
.scene .nsel__panels { display: block; }
.scene__panel { display: grid; gap: 16px; }
.scene__shot { display: block; aspect-ratio: 16 / 10; border-radius: clamp(18px, 2.2vw, 28px); overflow: hidden; background: var(--sunken); box-shadow: var(--shadow-float); transition: transform var(--t-press) ease-out; }
.scene__shot:active { transform: scale(.994); }
.scene__shot > img, .scene__shot > .x-plate { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
.scene__cap { display: grid; gap: 6px; padding-inline: 6px; }
.scene__what { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font-size: .9375rem; line-height: 1.45; color: var(--ink-2); }
.scene__what b { font-weight: 600; color: var(--ink); }
.scene__task { max-width: 60ch; font-size: .9375rem; color: var(--ink-2); text-wrap: pretty; }
.scene__task span { margin-right: 2px; font-weight: 550; color: var(--ink); }
.scene__for { font-size: .8125rem; line-height: 1.5; color: var(--ink-3); }
.scene__for b { font-weight: 550; color: var(--ink-2); }
.scene__for a { display: inline-block; padding-block: 9px; font-weight: 550; color: var(--ink); text-underline-offset: 3px; }
:lang(th) :is(.scene__what, .scene__task, .scene__for) { line-height: 1.7; }
/* The product bar over the opening's scene: one tab for each product on a soft track, the chosen one on a white
   pill; under it "Show it for" and the kinds of business, then the picture. All of it stands on one card. */
.pstage { position: relative; z-index: 1; display: grid; gap: 12px; padding: 10px; border-radius: 32px; background: var(--surface); box-shadow: var(--shadow-float); }
.pstage__tabs { position: relative; display: flex; gap: 2px; padding: 4px; border-radius: 22px; background: var(--sunken); overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity; }
.pstage__tabs::-webkit-scrollbar { display: none; }
.pstage__tab { position: relative; z-index: 1; flex: 1 0 auto; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; min-height: 44px; padding: 0 11px; border: 0; background: none; border-radius: 18px; font-size: .875rem; font-weight: 550; color: var(--ink-3); white-space: nowrap; scroll-snap-align: center; transition: color var(--t-fast) ease; }
.pstage__tab[aria-selected="true"] { color: var(--ink); }
.pstage__pill { position: absolute; left: 0; top: 4px; height: calc(100% - 8px); width: 100px; transform-origin: 0 50%; border-radius: calc(18px / var(--sx, 1)) / 18px; background: var(--surface); box-shadow: 0 0 0 1px var(--hair), 0 2px 6px rgba(var(--shade-rgb), .08); transition: transform var(--t-med) var(--ease); }
@media (min-width: 1000px) and (max-width: 1279px) { .pstage__tabs { gap: 0; } .pstage__tab { padding: 0 7px; font-size: .8125rem; letter-spacing: -.01em; } }
@media (min-width: 1000px) and (max-width: 1099px) { .pstage__tab { padding: 0 4px; font-size: .78125rem; } }
.pstage__panel { min-width: 0; }
.pstage__panel[hidden] { display: none; }
.pstage[data-live] .pstage__panel { animation: pstage-in 240ms var(--ease); }
@keyframes pstage-in { from { opacity: 0; transform: translateY(8px); } }
/* Without scripts the tabs are links to the products' pages, with no pill, over the first product's scene. */
.pstage:not([data-js]) .pstage__pill, .pstage:not([data-js]) .pstage__panel ~ .pstage__panel { display: none; }
.pstage:not([data-js]) .pstage__tab { color: var(--ink-2); }
.pstage .scene { display: grid; gap: 10px; }
.pstage .scene__panel { gap: 14px; }
.pstage .scene__shot { border-radius: 22px; box-shadow: inset 0 0 0 1px var(--hair); }
.pstage .scene__cap { padding: 0 8px 8px; }
.scene__pick { padding: 2px 8px 0; font-size: .8125rem; font-weight: 550; line-height: 1.3; color: var(--ink-3); }
.scene--pick .nsel__tabs { gap: 6px; padding-inline: 4px; }
.scene--pick .nsel__tab { min-height: 40px; padding: 0 14px; font-size: .875rem; white-space: nowrap; }
.scene:not([data-on]).scene--pick .scene__pick, .scene:not([data-on]).scene--pick .nsel__tabs { display: none; }
/* A tab with no example to open (AI assistant for LINE): a still of the chat, at a size that reads in the frame. */
.scene__shot--chat { display: grid; place-items: center; padding: clamp(14px, 4vw, 40px); text-decoration: none; }
.scene__shot--chat .chatpic { width: min(100%, 27rem); gap: 10px; padding: 0; font-size: clamp(.875rem, .8rem + .35vw, 1.0625rem); }
.scene__shot--chat .chatpic__msg { padding: 10px 15px; border-radius: 18px 18px 18px 6px; }
.scene__shot--chat .chatpic__msg--me { border-radius: 18px 18px 6px 18px; }
.scene__shot--chat .chatpic__src { font-size: .8125rem; }
.scene__go .link { min-height: 40px; }
@media (pointer: coarse) { .scene--pick .nsel__tab { min-height: 44px; } }
/* On a phone the kinds of business are one row that scrolls sideways, to the card's edges, so the picture stays
   near the top; src/js/stage.js keeps the chosen one in sight. */
@media (max-width: 639px) {
  .pstage .scene--pick .nsel__tabs { flex-wrap: nowrap; margin-inline: -10px; padding-inline: 14px; overflow-x: auto; overscroll-behavior-x: contain; scroll-padding-inline: 14px; scrollbar-width: none; }
  .pstage .scene--pick .nsel__tabs::-webkit-scrollbar { display: none; }
  .pstage .scene--pick .nsel__tabs li { flex: none; }
}
@media (prefers-reduced-motion: reduce) { .pstage__pill { transition: none; } .pstage[data-live] .pstage__panel { animation: none; } }
/* Without scripts (or if the script that runs the choice never arrives) the scene shows its first example. */
.scene:not([data-on]) .scene__panel ~ .scene__panel { display: none; }

/* Commissioned work, straight under the opening: a strip, not a section. Real work, labelled as such. */
.proofband { padding-block: clamp(20px, 3vw, 40px) clamp(36px, 5vw, 72px); }
.proof { display: grid; gap: 20px 28px; padding: 10px; border-radius: var(--r-xl); background: var(--surface); box-shadow: 0 0 0 1px var(--hair); }
.proof__top { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; padding: 8px 12px 0; }
.proof__count { font-size: .875rem; color: var(--ink-2); }
.proof__top .link { min-height: 40px; margin-inline-start: auto; font-size: .9375rem; }
.proof__img { display: block; aspect-ratio: 16 / 10; border-radius: 20px; overflow: hidden; background: var(--sunken); }
.proof__img img { width: 100%; height: 100%; object-fit: cover; object-position: left top; }
.proof__body { display: grid; gap: 8px; align-content: center; justify-items: start; min-width: 0; padding: 4px 12px 8px; }
.proof__h { font-size: 1.3125rem; line-height: 1.25; font-weight: 600; letter-spacing: var(--trk-head); }
.proof__h span, .proof__name span { display: block; margin-top: 2px; font-size: .875rem; font-weight: 400; letter-spacing: 0; color: var(--ink-3); }
.proof__built { max-width: 52ch; color: var(--ink-2); text-wrap: pretty; }
.proof__links .link { min-height: 44px; }
.proof__more { display: grid; align-content: center; padding: 0 12px 10px; }
.proof__more li { display: grid; gap: 6px; padding-block: 14px; border-top: 1px solid var(--hair); }
.proof__name { font-size: 1rem; line-height: 1.3; font-weight: 600; }
.proof__more .link { min-height: 32px; }
@media (min-width: 900px) {
  .proof { grid-template-columns: 300px minmax(0, 1.2fr) minmax(0, 1fr); align-items: stretch; }
  .proof__top { grid-column: 1 / -1; padding: 6px 12px 0 8px; }
  .proof__img { aspect-ratio: auto; height: 100%; min-height: 190px; }
  .proof__body { padding: 14px 0; }
  .proof__more { padding: 6px 18px 6px 28px; border-left: 1px solid var(--hair); }
  .proof__more li:first-child { border-top: 0; }
}
/* On a phone the strip stays a strip (the audit of 17 October 2026: proof close to the first screen): a wide, short
   picture, and the other projects as close lines. */
@media (max-width: 899px) {
  .proof { gap: 14px; }
  .proof__img { aspect-ratio: 21 / 9; }
  .proof__more li { padding-block: 11px; }
}

/* "What kind of business do you run?" The choices, and under them where O2 would start for the one chosen. */
.starts { gap: clamp(20px, 2.6vw, 30px); }
.starts__row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.starts__other { min-height: 44px; }
.start { display: grid; gap: clamp(20px, 3vw, 40px); padding: clamp(20px, 3vw, 36px); border-radius: var(--r-xl); background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.start__main { display: grid; gap: 10px; justify-items: start; align-content: start; min-width: 0; }
.start__h { font-size: clamp(1.625rem, 1.3rem + 1.3vw, 2.25rem); line-height: 1.14; font-weight: 600; letter-spacing: var(--trk-head); }
.start__h a { display: inline-flex; align-items: center; gap: 10px; color: inherit; text-decoration: none; }
.start__h .i { flex: none; width: .62em; height: .62em; color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.start__formal { margin-top: -6px; font-size: .875rem; font-weight: 500; color: var(--ink-3); }
.start__why { max-width: 56ch; color: var(--ink-2); text-wrap: pretty; }
.start__ex { display: grid; gap: 8px; width: 100%; max-width: 560px; margin-top: 8px; }
.start__ex-h, .start__add-h { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.start__ex .xt--compact { background: var(--surface); }
.start__links .link { min-height: 44px; }
.start__add { display: grid; gap: 4px; align-content: start; min-width: 0; }
.start__add ul { display: grid; margin-top: 6px; }
.start__add li { display: grid; gap: 2px; padding-block: 13px; border-top: 1px solid var(--hair); }
.start__add li:last-child { border-bottom: 1px solid var(--hair); }
.start__add li a { justify-self: start; font-weight: 600; text-decoration: none; }
.start__add li span { font-size: .9375rem; color: var(--ink-2); text-wrap: pretty; }
.start__add > p { margin-top: 8px; }
.start__add > p .link { min-height: 44px; }
:lang(th) :is(.start__why, .start__add li span) { line-height: 1.75; }
.starts--list { display: grid; gap: 14px; }
.starts--list .starts__one { display: grid; gap: 12px; }
@media (min-width: 900px) { .start { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); } .start__add { padding-left: clamp(20px, 3vw, 40px); border-left: 1px solid var(--hair); } }
/* The finder's entry, on a light band. */
.ask.ask--light { margin-top: clamp(20px, 2.6vw, 30px); background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.ask.ask--light .ask__label { color: var(--ink); }
.ask.ask--light .ask__label .i { color: var(--accent); }
.ask.ask--light textarea { background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair-2); color: var(--ink); }
.ask.ask--light textarea::placeholder { color: var(--ink-3); }
.ask.ask--light textarea:focus-visible { outline: none; box-shadow: inset 0 0 0 1.5px var(--accent), 0 0 0 4px var(--focus-halo); }
/* How O2 works: each stage says what the client provides and what O2 produces. */
.steps--pair dl { display: grid; gap: 12px; }
.steps--pair dt { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.steps--pair dd { margin-top: 2px; font-size: .9375rem; color: var(--ink-2); text-wrap: pretty; }
.founders__how { max-width: 46ch; color: var(--ink-2); }
.closing__direct { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 20px; padding-top: 20px; border-top: 1px solid var(--hair-dark); font-size: .9375rem; color: var(--on-dark-2); }
.closing__direct a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 550; color: var(--on-dark); text-decoration: none; }
.pidx__kicker .tag, .pcard__kicker .tag { margin-left: 8px; vertical-align: baseline; }
/* A fine echo of the mark's cut ring, behind the scene. Decorative. */
.hero__ring { position: absolute; z-index: 0; width: min(86vw, 700px); aspect-ratio: 1; right: -17%; top: 50%; translate: 0 -50%; border-radius: 50%; border: 1.5px solid rgba(var(--glow-rgb), .22); pointer-events: none; -webkit-mask: conic-gradient(from 22deg, #000 0 166deg, transparent 166deg 180deg, #000 180deg 346deg, transparent 346deg 360deg); mask: conic-gradient(from 22deg, #000 0 166deg, transparent 166deg 180deg, #000 180deg 346deg, transparent 346deg 360deg); }
@media (min-width: 1000px) {
  .hero__in { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
}
@media (max-width: 999px) { .hero__ring { right: -40%; top: 62%; } }

/* ---- the scripted chat ----------------------------------------------------- */
/* The AI LINE Assistant preview (src/demos.mjs): the one product shown by a small scripted
   interface. The other five products are shown through their full examples. */
.demo { position: relative; flex: 1; display: flex; flex-direction: column; gap: 14px; min-height: 336px; padding: 20px 20px 44px; border-radius: 22px; background: var(--canvas); font-size: .9375rem; line-height: 1.4; }
:lang(th) .demo { line-height: 1.56; }
.demo__badge { position: absolute; right: 16px; bottom: 14px; display: inline-flex; align-items: center; gap: 6px; font-size: .6875rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); pointer-events: none; }
.demo__badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
:lang(th) .demo__badge { letter-spacing: 0; font-size: .75rem; }
.demo button { transition: transform var(--t-press) ease-out, background-color var(--t-fast) ease, box-shadow var(--t-fast) ease, color var(--t-fast) ease; touch-action: manipulation; }
.demo button:active { transform: scale(.97); }
.dpane { display: flex; flex-direction: column; gap: 10px; flex: 1; animation: pane var(--t-med) var(--ease); }
@keyframes pane { from { opacity: 0; transform: translateY(6px); } }
.dlabel, .dnote { font-size: .8125rem; color: var(--ink-3); }
.dlink { align-self: flex-start; min-height: 36px; padding: 0 2px; background: none; border: 0; color: var(--accent-press); font-weight: 550; font-size: .875rem; }
.dlist { display: grid; gap: 6px; }
.drow { display: flex; align-items: center; justify-content: space-between; min-height: 48px; padding: 0 16px; border-radius: 14px; border: 0; background: var(--surface); box-shadow: 0 0 0 1px var(--hair); font-weight: 500; text-align: left; }
.drow .i { color: var(--ink-4); }
.dchat__bar { display: flex; align-items: center; gap: 10px; }
.dchat__name { font-size: .8125rem; color: var(--ink-3); font-weight: 500; }
.dchat__log { display: flex; flex-direction: column; gap: 8px; }
.dmsg { align-self: flex-start; max-width: 88%; padding: 9px 13px; border-radius: 16px 16px 16px 6px; background: var(--surface); box-shadow: 0 0 0 1px var(--hair); animation: pane var(--t-med) var(--ease); }
.dmsg--me { align-self: flex-end; border-radius: 16px 16px 6px 16px; background: var(--accent-soft); box-shadow: none; }
.dmsg__src { align-self: flex-start; margin: -4px 0 0 4px; font-size: .75rem; color: var(--ink-3); }
.dmsg--staff { align-self: center; max-width: 100%; padding: 6px 13px; border-radius: var(--pill); background: var(--warn-soft); color: var(--warn); box-shadow: none; font-size: .8125rem; font-weight: 550; text-align: center; }
.dmsg--typing { display: inline-flex; gap: 4px; padding: 14px 13px; }
.dmsg--typing[hidden] { display: none; }
.dmsg--typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); animation: typing 1s ease-in-out infinite; }
.dmsg--typing i:nth-child(2) { animation-delay: .15s; }
.dmsg--typing i:nth-child(3) { animation-delay: .3s; }
@keyframes typing { 0%, 60%, 100% { opacity: .35; transform: none; } 30% { opacity: 1; transform: translateY(-2px); } }

/* ---- product cards -------------------------------------------------------- */
.pgrid { display: grid; gap: 14px; }
.pcard { position: relative; display: flex; flex-direction: column; gap: 10px; padding: clamp(22px, 2.6vw, 32px); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); transition: box-shadow var(--t-med) var(--ease), opacity var(--t-med) ease; }
.band--tint .pcard { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.pcard__icon { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 13px; color: var(--ink); box-shadow: inset 0 0 0 1px var(--hair-2); margin-bottom: 10px; }
.glyph { width: 24px; height: 24px; }
.pcard__name { font-size: 1.375rem; line-height: 1.2; letter-spacing: var(--trk-head); font-weight: 600; }
:lang(th) .pcard__name { line-height: 1.4; }
.pcard__short { color: var(--ink-2); max-width: 46ch; }
.pcard__caps { margin-top: 8px; font-size: .9375rem; color: var(--ink-2); }
.pcard__best { font-size: .875rem; color: var(--ink-3); margin-top: 6px; }
.pcard__best span { font-weight: 550; color: var(--ink-2); }
/* Where a product stands, and what to keep in mind (Phase 5): two quiet lines in the card's own type, not badges. */
.pcard__facts { display: grid; gap: 2px; margin: 6px 0 0; font-size: .875rem; line-height: 1.45; color: var(--ink-3); }
.pcard__facts dt { display: inline; margin-inline-end: 6px; font-weight: 550; color: var(--ink-2); }
.pcard__facts dd { display: inline; margin: 0; }
.pcard__extra { display: grid; gap: 8px; }
.pcard__toggle { display: none; }
/* A phone with scripting: the card's summary first, its details one tap away (src/lib/parts.mjs productCard). */
@media (scripting: enabled) and (max-width: 639px) {
  .pcard__toggle { display: inline-flex; align-items: center; gap: 8px; align-self: flex-start; min-height: 40px; margin: 0; padding: 0; border: 0; background: none; color: var(--ink); font: inherit; font-size: .9375rem; font-weight: 550; cursor: pointer; touch-action: manipulation; }
  .pcard__toggle::after { content: ""; width: 7px; height: 7px; border-right: 1.75px solid var(--ink-3); border-bottom: 1.75px solid var(--ink-3); transform: rotate(45deg) translate(-2px, -2px); transition: transform var(--t-fast) var(--ease); }
  .pcard__toggle[aria-expanded="true"]::after { transform: rotate(-135deg) translate(-2px, -2px); }
  .pcard__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
  .pcard__toggle[aria-expanded="false"] + .pcard__extra { display: none; }
}
@media (prefers-reduced-motion: reduce) { .pcard__toggle::after { transition: none; } }
.pcard__actions { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; justify-content: space-between; margin-top: auto; padding-top: 18px; }
.pcard__link { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; font-weight: 550; text-decoration: none; }
.pcard__link .i { color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.pcard__link::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-xl); }
.pcard .js-add, .pcard__compare { position: relative; z-index: 1; }
.pcard__compare { display: inline-flex; align-items: center; gap: 8px; min-height: 36px; font-size: .875rem; color: var(--ink-3); align-self: flex-start; cursor: pointer; }
.pcard__compare input { width: 17px; height: 17px; accent-color: var(--ink); }
@media (min-width: 640px) { .pgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) {
  .pgrid { grid-template-columns: repeat(6, 1fr); }
  .pgrid > .pcard { grid-column: span 2; }
}
.pgrid--pair, .pgrid--filtered { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.pgrid--pair > .pcard, .pgrid--filtered > .pcard, .pgrid--pair > .pcard:nth-child(-n+2), .pgrid--filtered > .pcard:nth-child(-n+2) { grid-column: auto; }
.pgrid--filtered > .pcard { max-width: 640px; }
.note { margin-top: 22px; max-width: 64ch; }

/* ---- work cards ----------------------------------------------------------- */
.wgrid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.wcard { display: flex; flex-direction: column; padding: 8px; border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); transition: box-shadow var(--t-med) var(--ease); }
.band--tint .wcard { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.wcard__img { border-radius: 21px; background: var(--sunken); overflow: hidden; aspect-ratio: 16 / 10; }
.wcard__img img { width: 100%; height: 100%; object-fit: cover; object-position: left top; transition: transform 900ms var(--ease); }
.wcard__body { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; gap: 6px; padding: clamp(16px, 2vw, 22px) clamp(14px, 1.8vw, 20px) clamp(14px, 1.8vw, 20px); align-content: start; }
.wcard__name { font-size: 1.3125rem; line-height: 1.22; font-weight: 600; letter-spacing: var(--trk-head); margin-top: 8px; }
.wcard__built { color: var(--ink-2); margin-top: 6px; }
.wcard__note { margin-top: 2px; }
.wcard__links { display: flex; flex-wrap: wrap; gap: 6px 22px; margin-top: 10px; }
.wcard--feature .wcard__name { font-size: clamp(1.5rem, 1.15rem + 1.1vw, 2rem); }
.wcard__story { color: var(--ink-2); margin-top: 6px; text-wrap: pretty; }
.wcard__k { display: block; margin-bottom: 2px; font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
/* The Work page: the case study across the page, picture beside the story, and the other projects in one row. */
@media (min-width: 900px) {
  .wgrid--lead { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .wgrid--lead .wcard--feature { grid-column: 1 / -1; flex-direction: row; align-items: stretch; }
  .wgrid--lead .wcard--feature .wcard__img { flex: 0 0 58%; aspect-ratio: auto; min-height: 380px; }
  .wgrid--lead .wcard--feature .wcard__body { align-content: center; padding-inline: clamp(22px, 3vw, 40px); }
  .wgrid--lead .wcard--feature .wcard__story, .wgrid--lead .wcard--feature .wcard__built { max-width: 46ch; }
}
@media (min-width: 720px) { .wgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .wgrid--home .wcard--feature { grid-column: 1 / -1; } }
@media (min-width: 1000px) {
  .wgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .wgrid--home, .wgrid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The lead project: its capture at full width beside a short account of it. */
  .wgrid--home .wcard--feature { flex-direction: row; align-items: stretch; }
  .wgrid--home .wcard--feature .wcard__img { flex: 0 0 63%; aspect-ratio: 2000 / 895; }
  .wgrid--home .wcard--feature .wcard__img img { object-position: left top; }
  .wgrid--home .wcard--feature .wcard__body { align-content: center; padding-inline: clamp(22px, 3vw, 40px); }
  .wgrid--home .wcard:not(.wcard--feature) { flex-direction: row; }
  .wgrid--home .wcard:not(.wcard--feature) .wcard__img { flex: 0 0 46%; aspect-ratio: 16 / 11; }
  .wgrid--home .wcard:not(.wcard--feature) .wcard__body { align-content: center; }
  .wgrid--home .wcard:not(.wcard--feature) .wcard__built { display: none; }
}

/* ---- routes and the finder entry on dark ---------------------------------- */
.routes { display: grid; gap: 10px; }
.route { position: relative; display: grid; gap: 8px; height: 100%; padding: 22px 52px 24px 22px; border-radius: var(--r-l); box-shadow: inset 0 0 0 1px var(--hair-dark); background: rgba(255, 255, 255, .035); text-decoration: none; transition: background-color var(--t-fast) ease, transform var(--t-press) ease-out; }
.route:active { transform: scale(.985); }
.route__h { font-size: 1.25rem; font-weight: 600; letter-spacing: var(--trk-head); }
.route__p { font-size: .9375rem; color: var(--on-dark-2); }
.route .i { position: absolute; right: 22px; top: 27px; color: var(--on-dark-accent); transition: transform var(--t-fast) var(--ease); }
@media (min-width: 640px) { .routes { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .routes { grid-template-columns: repeat(4, 1fr); } }
.ask { margin-top: 10px; padding: 22px; border-radius: var(--r-l); background: var(--dark-2); box-shadow: inset 0 0 0 1px var(--hair-dark); }
.ask__label { display: inline-flex; align-items: center; gap: 8px; font-weight: 550; color: var(--on-dark); margin-bottom: 14px; }
.ask__label .i { color: var(--on-dark-accent); }
.ask__row { display: grid; gap: 12px; }
.ask textarea { width: 100%; min-height: 76px; resize: vertical; padding: 14px 16px; border-radius: var(--r-m); border: 0; box-shadow: inset 0 0 0 1px var(--hair-dark); background: rgba(255, 255, 255, .05); color: var(--on-dark); line-height: 1.45; }
.ask textarea::placeholder { color: #8591A6; }
.ask textarea:focus-visible { outline-color: var(--on-dark-accent); }
@media (min-width: 760px) { .ask__row { grid-template-columns: 1fr auto; align-items: end; } }

/* ---- steps ---------------------------------------------------------------- */
.steps { display: grid; gap: 28px 24px; }
.steps li { display: grid; gap: 8px; align-content: start; padding-top: 18px; border-top: 1px solid var(--hair-2); }
.steps p { color: var(--ink-2); }
.steps__n { font-size: .8125rem; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; letter-spacing: .04em; margin-bottom: 14px; }
@media (min-width: 640px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .steps--4 { grid-template-columns: repeat(4, 1fr); } }

/* ---- founders ------------------------------------------------------------- */
.founders { display: grid; gap: clamp(28px, 5vw, 80px); align-items: center; }
.founders__img { border-radius: var(--r-xl); overflow: hidden; background: var(--sunken); aspect-ratio: 4 / 4.5; max-height: 560px; }
.founders__img img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 24%; }
.founders__copy { display: grid; gap: 22px; justify-items: start; }
.founders__copy .h2 { max-width: 16ch; }
.founders__copy .lead { max-width: 44ch; }
@media (min-width: 900px) { .founders { grid-template-columns: minmax(0, 4fr) minmax(0, 6fr); } }

/* ---- closing + footer ----------------------------------------------------- */
.closing__in { display: grid; gap: 28px; align-items: center; }
.closing .lead { margin-top: 14px; max-width: 46ch; }
.closing__actions { display: flex; flex-wrap: wrap; gap: 12px; }
@media (min-width: 900px) { .closing__in { grid-template-columns: 1fr auto; } }
.foot { background: var(--dark); color: var(--on-dark-2); border-top: 1px solid var(--hair-dark); padding-block: clamp(40px, 5vw, 64px) calc(28px + env(safe-area-inset-bottom)); font-size: .9375rem; }
.foot :focus-visible { outline-color: var(--on-dark-accent); }
.foot .small { color: var(--on-dark-2); }
.foot__grid { display: grid; gap: 32px 24px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.foot__brand { grid-column: 1 / -1; display: grid; gap: 8px; align-content: start; }
.foot__logo { display: inline-flex; align-items: center; gap: 12px; min-height: 44px; color: var(--on-dark); text-decoration: none; font-size: .6875rem; letter-spacing: .2em; text-transform: uppercase; font-weight: 550; }
.foot__h { font-size: .8125rem; font-weight: 550; color: var(--on-dark); margin-bottom: 8px; }
.foot a { display: inline-flex; align-items: center; min-height: 36px; overflow-wrap: anywhere; text-decoration: none; transition: color var(--t-fast) ease; }
.foot__base { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px; margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--hair-dark); }
.lang--foot a { color: var(--on-dark-2); }
.lang--foot a[aria-current="true"] { color: var(--on-dark); }
.lang--foot a + a::before { border-color: var(--hair-dark); }
@media (min-width: 900px) { .foot__grid { grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr)); } .foot__brand { grid-column: auto; } }
body:has(.tray:not([hidden])) .foot { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
/* The tray floats over the foot of the window. Whatever is scrolled into view, by Tab or by a link to
   a place on the page, comes to rest above it and not underneath. */
html:has(.tray:not([hidden])) { scroll-padding-bottom: calc(96px + env(safe-area-inset-bottom)); }

/* ---- enquiry shortlist tray: a floating material -------------------------- */
.tray { position: fixed; z-index: 80; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom)); width: min(540px, calc(100vw - 24px)); transform: translateX(-50%); border-radius: 26px; background: var(--tray-bg); -webkit-backdrop-filter: saturate(180%) blur(24px); backdrop-filter: saturate(180%) blur(24px); color: var(--on-dark); box-shadow: 0 12px 44px -8px rgba(16, 21, 34, .4), inset 0 1px 0 rgba(255, 255, 255, .14), inset 0 0 0 1px rgba(255, 255, 255, .06); }
/* Its entrance is for the moment something is first saved. A page that opens with a shortlist shows the bar in place. */
.tray--new { animation: tray-in 520ms var(--ease); }
@keyframes tray-in { from { opacity: 0; transform: translateX(-50%) translateY(18px) scale(.96); } }
.tray__in { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 8px 8px 10px; }
.tray__sum { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 8px; border: 0; background: none; color: inherit; font-size: .9375rem; font-weight: 500; text-align: left; border-radius: 14px; min-width: 0; }
/* The bar is dark in both themes, so its count keeps one blue and white figures: the dark theme's accent is too pale to carry them. */
.tray__count { display: inline-grid; place-items: center; min-width: 26px; height: 26px; padding: 0 6px; border-radius: var(--pill); background: #245BFF; color: #fff; font-weight: 600; font-size: .8125rem; font-variant-numeric: tabular-nums; flex: none; }
.tray :focus-visible { outline-color: var(--on-dark-accent); }
.tray__list { padding: 4px 18px 14px; border-top: 1px solid var(--hair-dark); }
.tray__list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 46px; font-size: .9375rem; }
.tray__list li + li { border-top: 1px solid var(--hair-dark); }
.tray__list li button { display: inline-flex; align-items: center; min-height: 36px; padding: 0 4px; border: 0; background: none; color: var(--on-dark-accent); font-size: .875rem; font-weight: 550; }
.tray__list .link { color: var(--on-dark-accent); margin-top: 8px; font-size: .875rem; }
@media (max-width: 460px) { .tray #tray-text { font-size: .8125rem; } .tray .btn .i { display: none; } }
/* The control that makes the bar small sits on its corner, so it takes no room from the words. Its touch area is 44px. */
.tray__min { position: absolute; top: -9px; right: -5px; display: grid; place-items: center; width: 26px; height: 26px; border: 0; border-radius: 50%; background: var(--dark-2); color: var(--on-dark-2); box-shadow: inset 0 0 0 1px var(--hair-dark), 0 2px 8px rgba(16, 21, 34, .3); }
.tray__min::after { content: ""; position: absolute; inset: -9px; }
.tray__min .i { width: 12px; height: 12px; }
/* Made small: the count alone, in the corner. Its words stay in the button's name. */
.tray[data-mini] { left: auto; right: calc(14px + env(safe-area-inset-right)); width: auto; transform: none; animation: none; }
.tray[data-mini] .tray__in { padding: 6px; }
.tray[data-mini] .tray__sum { padding: 0 9px; }
.tray[data-mini] #tray-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.tray[data-mini] #tray-go, .tray[data-mini] .tray__min { display: none; }
/* The contact form: a draft that came back, and the recap beside the Send button. */
.kept { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 16px; margin-bottom: 18px; }
.kept .link { color: inherit; font-weight: 550; min-height: 32px; }
.review { margin-top: 26px; padding: 18px 20px 16px; border-radius: var(--r-l); background: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair); }
.review .plan__list > div:first-child { border-top: 0; padding-top: 0; }
.review__h { font-size: .9375rem; font-weight: 600; margin-bottom: 8px; }
.review .plan__list > div:last-child { border-bottom: 0; }
.review__next { margin-top: 10px; font-size: .875rem; color: var(--ink-2); }

/* ---- product detail ------------------------------------------------------- */
.pd { position: relative; overflow: clip; padding-block: clamp(22px, 3.2vw, 46px) clamp(30px, 3.6vw, 50px); }
.pd::before { content: ""; position: absolute; inset: -20% -10% 0 34%; pointer-events: none; background: radial-gradient(44% 44% at 62% 40%, rgba(var(--glow-rgb), .11), transparent 70%); }
.pd__in { position: relative; display: grid; gap: clamp(28px, 4.4vw, 64px); align-items: center; }
.pd .eyebrow + .h1 { margin-top: 14px; }
.pd .h1 { max-width: 14ch; }
.pd .lead { margin-top: 18px; max-width: 36ch; }
.pd .actions { margin-top: 30px; }
/* The opening of a product page shows the product: the first screen of a working example, beside its name.
   Under them, four short answers to the buying question. */
.pd__scene { position: relative; min-width: 0; }
.pd__stage { margin-top: 12px; }
.pd__stage + .lead { margin-top: 12px; }
.pd__reach { margin-top: 12px; max-width: 44ch; color: var(--ink-2); text-wrap: pretty; }
.pd-strip { position: relative; display: grid; gap: 0; margin-top: clamp(28px, 3.6vw, 48px); border-top: 1px solid var(--hair-2); }
.pd-strip > div { display: grid; gap: 4px; align-content: start; padding: 16px 0; border-bottom: 1px solid var(--hair); }
.pd-strip dt { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.pd-strip dd { font-size: .9375rem; line-height: 1.5; color: var(--ink); text-wrap: pretty; }
.pd-strip__list { display: grid; gap: 4px; }
.pd-strip__list li { position: relative; padding-left: 16px; }
.pd-strip__list li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
:lang(th) .pd-strip__list li::before { top: .8em; }
.pd-strip__more { min-height: 40px; margin-top: 2px; font-size: .9375rem; }
:lang(th) .pd-strip dd { line-height: 1.72; }
@media (min-width: 720px) { .pd-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(20px, 3vw, 40px); } }
@media (min-width: 1100px) { .pd-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); } .pd-strip > div { border-bottom: 0; padding-bottom: 0; } }
@media (min-width: 1000px) { .pd__in--scene { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); align-items: start; } .pd__in--scene .pd__copy { padding-top: clamp(0px, 3vh, 36px); } }
/* Beside the scripted conversation, which grows as it is played, the words stay at the top. */
@media (min-width: 1000px) { .pd__in--demo { align-items: start; } .pd__in--demo .pd__copy { padding-top: clamp(0px, 3vh, 36px); } }
/* The chosen example's own details, where the opening already shows its picture. */
.xt--text .xt__in { display: block; }
.pd__demo { background: var(--surface); border-radius: 32px; box-shadow: var(--shadow-float); padding: 10px; min-width: 0; }
.pd__demo .demo { min-height: 360px; }
.pd__cap { padding: 12px 10px 6px; }
@media (min-width: 1000px) { .pd__in { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); } }

.sit { display: grid; gap: 0 32px; }
.sit li { padding: 20px 0; border-top: 1px solid var(--hair-2); font-size: 1.125rem; font-weight: 500; line-height: 1.38; letter-spacing: var(--trk-sub); text-wrap: pretty; }
:lang(th) .sit li { line-height: 1.62; }
@media (min-width: 640px) { .sit { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .sit { grid-template-columns: repeat(4, 1fr); } .sit li { padding-bottom: 8px; } }
/* Five signs: three and two on a tablet, one row of five on a wide screen, never one left alone. */
@media (min-width: 640px) { .sit--5 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1100px) { .sit--5 { grid-template-columns: repeat(5, 1fr); } }
.svc-signs-link { margin-top: 20px; }
.svc-order { display: grid; gap: 40px 64px; }
.svc-order .ticks { margin-top: 20px; }
.svc-order .lead { margin-top: 16px; max-width: 46ch; }
.svc-order__h { margin-top: 28px; }
/* Each guide on its own line, the arrow straight after the words even when a title wraps. */
.svc-order__links { display: grid; justify-items: start; gap: 6px; margin-top: 8px; }
.svc-order__links .link { display: inline; min-height: 0; line-height: 1.5; }
.svc-order__links .link .i { display: inline-block; vertical-align: -3px; margin-left: 6px; }
@media (min-width: 900px) { .svc-order { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

/* The journey: numbered stops along one line, down the page on a phone and across it from 900px. */
.flow { --flow-gap: clamp(20px, 2.6vw, 36px); display: grid; counter-reset: f; }
.flow li { position: relative; display: grid; gap: 4px; align-content: start; padding: 3px 0 28px 50px; counter-increment: f; }
.flow li:last-child { padding-bottom: 0; }
.flow li::before { content: counter(f); position: absolute; left: 0; top: 0; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair-2); font-size: .875rem; line-height: 1; font-weight: 600; font-variant-numeric: tabular-nums; }
.band--tint .flow li::before { background: var(--canvas); }
.flow li::after { content: ""; position: absolute; left: 15.5px; top: 38px; bottom: 6px; border-left: 1px solid var(--hair-2); }
.flow li:last-child::after { display: none; }
.flow h3 { font-size: 1.0625rem; line-height: 1.35; font-weight: 600; letter-spacing: var(--trk-sub); }
:lang(th) .flow h3 { line-height: 1.5; }
.flow p { font-size: 1rem; color: var(--ink-2); max-width: 44ch; }
@media (min-width: 900px) {
  .flow { grid-auto-flow: column; grid-auto-columns: 1fr; column-gap: var(--flow-gap); }
  .flow li { padding: 48px 0 0; }
  .flow li::after { left: 40px; right: calc(8px - var(--flow-gap)); top: 15.5px; bottom: auto; border-left: 0; border-top: 1px solid var(--hair-2); }
}

.split { display: grid; gap: clamp(32px, 5vw, 80px); }
.split h2 { margin-bottom: 22px; }
.callout { margin-top: 24px; padding: 18px 20px; border-radius: var(--r-m); background: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair); color: var(--ink-2); font-size: .9375rem; }
.band:not(.band--tint) .callout { background: var(--surface); }
.bund { display: grid; gap: 14px; margin-top: 14px; }
.bund dt { font-weight: 600; }
.bund dd { font-size: .9375rem; color: var(--ink-2); margin-top: 2px; }
@media (min-width: 900px) { .split { grid-template-columns: 1fr 1fr; } }

.faq { max-width: 820px; border-bottom: 1px solid var(--hair-2); }
.faq details { border-top: 1px solid var(--hair-2); }
.faq summary { display: flex; align-items: center; justify-content: space-between; gap: 20px; min-height: 64px; padding: 14px 0; font-size: 1.0625rem; font-weight: 550; letter-spacing: var(--trk-sub); cursor: pointer; list-style: none; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: ""; flex: none; width: 9px; height: 9px; margin-right: 4px; border-right: 1.75px solid var(--ink-3); border-bottom: 1.75px solid var(--ink-3); transform: rotate(45deg) translate(-2px, -2px); transition: transform var(--t-med) var(--ease); }
.faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.faq details p { padding: 0 40px 22px 0; color: var(--ink-2); max-width: 66ch; }

/* ---- products index: goals + comparison ----------------------------------- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.chip { display: inline-flex; align-items: center; min-height: 42px; padding: 0 17px; border-radius: var(--pill); border: 0; background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair-2); font-size: .9375rem; font-weight: 500; color: var(--ink); transition: transform var(--t-press) ease-out, background-color var(--t-fast) ease, box-shadow var(--t-fast) ease, color var(--t-fast) ease; touch-action: manipulation; text-decoration: none; }
.chip:active { transform: scale(.97); }
.chip[aria-pressed="true"] { background: var(--ink); box-shadow: none; color: var(--on-ink); }
.chips__label { font-size: .875rem; color: var(--ink-3); margin-right: 6px; }
.chip--s { min-height: 36px; padding: 0 14px; font-size: .875rem; }
@media (pointer: coarse) { .chip--s { min-height: 44px; } }
.filter { margin-bottom: 22px; }
.cmp { margin-top: clamp(32px, 4.4vw, 56px); }

/* ---- forms ---------------------------------------------------------------- */
.card { padding: clamp(22px, 3vw, 36px); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); }
.field { display: grid; gap: 7px; }
.field + .field, .fieldset + .field, .field + .fieldset, .fieldset + .fieldset { margin-top: 20px; }
.field label, .fieldset legend, .field__label { font-size: .9375rem; font-weight: 550; padding: 0; }
.field__hint { font-size: .8125rem; font-weight: 400; color: var(--ink-3); }
.field input[type="text"], .field input[type="email"], .field input[type="tel"], .field textarea {
  width: 100%; min-height: 50px; padding: 13px 15px; border-radius: var(--r-m); border: 0; box-shadow: inset 0 0 0 1px var(--hair-2); background: var(--surface); line-height: 1.4;
  transition: box-shadow var(--t-fast) ease;
}
.field textarea { resize: vertical; min-height: 116px; }
.field input:focus-visible, .field textarea:focus-visible { outline: none; box-shadow: inset 0 0 0 1.5px var(--accent), 0 0 0 4px var(--focus-halo); }
.field [aria-invalid="true"] { box-shadow: inset 0 0 0 1.5px var(--err); }
.field__err { font-size: .875rem; color: var(--err); font-weight: 500; }
.fieldset { border: 0; padding: 0; margin: 0; min-width: 0; display: grid; gap: 10px; }
.grid2 { display: grid; gap: 20px; }
.grid2 > .field + .field { margin-top: 0; }
@media (min-width: 640px) { .grid2 { grid-template-columns: 1fr 1fr; } }
.radio { position: relative; display: inline-flex; }
.radio input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.radio span { display: inline-flex; align-items: center; min-height: 42px; padding: 0 17px; border-radius: var(--pill); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair-2); font-size: .9375rem; font-weight: 500; transition: background-color var(--t-fast) ease, box-shadow var(--t-fast) ease, color var(--t-fast) ease, transform var(--t-press) ease-out; }
.radio input:checked + span { background: var(--ink); box-shadow: none; color: var(--on-ink); }
.radio input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 3px; }
.radio input:active + span { transform: scale(.97); }
.alert { padding: 15px 18px; border-radius: var(--r-m); font-size: .9375rem; }
.alert--err { background: var(--err-soft); color: var(--alert-err); }
.alert--info { background: var(--accent-soft); color: var(--alert-info); }
.alert--warn { background: var(--warn-soft); color: var(--alert-warn); }
.alert a { font-weight: 550; }
.alert ul { margin-top: 6px; padding-left: 18px; list-style: disc; }
.counter { font-size: .8125rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.counter[data-over] { color: var(--err); font-weight: 600; }
.more { margin-top: 22px; border-top: 1px solid var(--hair); padding-top: 6px; }
.more summary { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; font-weight: 550; color: var(--ink); cursor: pointer; list-style: none; }
.more summary::-webkit-details-marker { display: none; }
.more summary::before { content: "+"; font-size: 1.25rem; font-weight: 400; line-height: 1; color: var(--accent); }
.more[open] summary::before { content: "−"; }
.spinner { width: 17px; height: 17px; border-radius: 50%; border: 1.75px solid currentColor; border-right-color: transparent; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- finder --------------------------------------------------------------- */
.finder { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; padding-bottom: var(--band); }
.finder__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-top: 22px; }
.mode { display: inline-flex; align-items: center; gap: 8px; font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.mode::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); }
.mode[data-mode="ai"]::before { background: var(--accent); }
.results { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; align-content: start; scroll-margin-top: calc(var(--nav-h) + 16px); }
.results:focus { outline: none; }
.rec { display: grid; gap: 14px; padding: clamp(22px, 2.8vw, 32px); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); animation: rise var(--t-slow) var(--ease) backwards; }
.rec--primary { box-shadow: 0 0 0 1.5px var(--accent), 0 16px 40px -20px rgba(var(--glow-rgb), .35); }
.rec + .rec { animation-delay: 90ms; }
.rec + .rec + .rec { animation-delay: 180ms; }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } }
.rec__head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; }
.rec__name { font-size: 1.5rem; line-height: 1.18; font-weight: 600; letter-spacing: var(--trk-head); }
.rec__why { color: var(--ink-2); max-width: 60ch; }
.rec__note { font-size: .875rem; color: var(--ink-3); padding-top: 14px; border-top: 1px solid var(--hair); }
.sum { padding: 20px 22px; border-radius: var(--r-l); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair); display: grid; gap: 8px; }
.sum h2 { font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.sum h2:not(:first-child) { margin-top: 8px; }
.sum ul { font-size: .9375rem; color: var(--ink-2); display: grid; gap: 4px; }
.sum ul li { position: relative; padding-left: 16px; }
.sum ul li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 5px; height: 5px; border-radius: 50%; background: var(--ink-4); }
.sum .link { justify-self: start; font-size: .875rem; }
.qbox { display: grid; gap: 16px; padding: clamp(22px, 2.8vw, 32px); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); animation: rise var(--t-slow) var(--ease) backwards; }
@media (min-width: 900px) { .finder { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); align-items: start; gap: 20px; } .finder__form { position: sticky; top: calc(var(--nav-h) + 16px); } }

/* ---- contact -------------------------------------------------------------- */
.contact { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; padding-bottom: var(--band); align-items: start; }
.direct { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; }
.direct a { font-weight: 550; text-decoration: none; display: inline-flex; min-height: 36px; align-items: center; overflow-wrap: anywhere; }
.direct dt { font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.direct dl { display: grid; grid-template-columns: minmax(0, 1fr); }
.direct dl > div { padding: 14px 0; border-top: 1px solid var(--hair); }
.picked { display: grid; gap: 0; width: 100%; }
.picked li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 0; border-top: 1px solid var(--hair); font-weight: 550; }
.done { display: grid; gap: 16px; justify-items: start; }
.done__tick { display: inline-grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: var(--ok); color: var(--on-accent); }
.done__tick .i { width: 24px; height: 24px; }
.done__tick .i-check { display: block; }
@media (min-width: 900px) { .contact { grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: 20px; } }

/* ---- industries, how it works, about, case study, legal ------------------- */
.ind { scroll-margin-top: calc(var(--nav-h) + 12px); }
.ind__in { display: grid; gap: clamp(24px, 4vw, 64px); }
.ind__head { display: grid; gap: 18px; justify-items: start; align-content: start; }
.needs { display: grid; gap: 0; }
.need { display: grid; gap: 6px; padding: 20px 0; border-top: 1px solid var(--hair-2); }
.need__q { font-size: 1.125rem; font-weight: 600; letter-spacing: var(--trk-sub); }
.need__a { color: var(--ink-2); }
.need__a a { display: inline-flex; align-items: center; gap: 5px; color: var(--ink); font-weight: 550; text-decoration: none; margin-right: 6px; }
.need__a a .i { color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.need--card { padding: 20px 22px; border: 0; border-radius: var(--r-l); background: var(--surface); box-shadow: var(--shadow-card); }
.band--tint .need--card { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.flowline { color: var(--ink-2); padding: 18px 20px; border-radius: var(--r-m); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair); font-size: .9375rem; }
.band--tint .flowline { background: var(--canvas); }
.flowline b { color: var(--ink); font-weight: 600; }
@media (min-width: 900px) { .ind__in { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); } .ind__head { position: sticky; top: calc(var(--nav-h) + 24px); } }

.stages { display: grid; counter-reset: st; border-bottom: 1px solid var(--hair-2); }
.stagecard { counter-increment: st; padding: clamp(24px, 3vw, 36px) 0; border-top: 1px solid var(--hair-2); display: grid; gap: 18px; }
.stagecard__head { display: flex; align-items: baseline; gap: 18px; }
.stagecard__head::before { content: counter(st, decimal-leading-zero); flex: none; width: 2.2em; font-size: .8125rem; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.stagecard__head h2 { font-size: clamp(1.375rem, 1.2rem + .7vw, 1.75rem); letter-spacing: var(--trk-head); line-height: 1.2; font-weight: 600; }
.stagecard__cols { display: grid; gap: 16px; }
.stagecard__cols h3 { font-size: .8125rem; font-weight: 550; color: var(--ink-3); margin-bottom: 5px; }
.stagecard__cols p { color: var(--ink-2); max-width: 46ch; }
@media (min-width: 760px) { .stagecard { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); gap: 24px; } .stagecard__cols { grid-template-columns: 1fr 1fr; gap: 32px; } }

.about { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 5vw, 88px); align-items: start; padding-block: clamp(24px, 3.6vw, 56px) var(--band); }
.about__img { border-radius: var(--r-xl); overflow: hidden; background: var(--sunken); }
.about__img img { width: 100%; }
.about__text .h1 { margin-top: 16px; max-width: 12ch; }
.profile { margin-top: 32px; padding-top: 22px; border-top: 1px solid var(--hair-2); display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.profile p { color: var(--ink-2); max-width: 46ch; }
.profile .profile__n { font-size: .8125rem; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; letter-spacing: .04em; }
@media (min-width: 900px) { .about { grid-template-columns: minmax(0, 4.4fr) minmax(0, 6fr); } .about__img { position: sticky; top: calc(var(--nav-h) + 24px); } }
.profile .pull { max-width: 20ch; color: var(--ink); }
.pull + p { margin-top: 14px; max-width: 54ch; }
.ops { display: grid; gap: 0 40px; margin-top: 32px; }
.ops p { color: var(--ink-2); padding: 20px 0; border-top: 1px solid var(--hair-2); font-size: 1.0625rem; }
@media (min-width: 900px) { .ops { grid-template-columns: repeat(3, 1fr); } }

.cs__head { display: grid; gap: 12px; }
.cs__head .h1 { margin-top: 6px; }
.cs__vis { display: grid; gap: 16px; align-items: end; }
.cs__vis figure { display: grid; gap: 12px; }
.cs__vis img { border-radius: var(--r-l); box-shadow: var(--shadow-lift); width: 100%; }
.cs__vis figcaption { font-size: .875rem; color: var(--ink-3); }
@media (max-width: 899px) {
  .cs__vis figure.is-portrait { justify-items: center; }
  .cs__vis figure.is-portrait img { width: min(100%, 17.5rem); }
  .cs__vis figure.is-portrait figcaption { text-align: center; }
}
@media (min-width: 900px) { .cs__vis { grid-template-columns: minmax(0, 2.6fr) minmax(0, 1fr); gap: 24px; } }

.legal { padding-bottom: var(--band); }
.legal h2 { font-size: 1.375rem; font-weight: 600; letter-spacing: var(--trk-head); margin: 0 0 12px; padding-top: 28px; border-top: 1px solid var(--hair-2); }
.legal h2:not(:first-child) { margin-top: 32px; }
.legal p, .legal li { color: var(--ink-2); max-width: 68ch; }
.legal p + p { margin-top: 12px; }
.legal ul { list-style: disc; padding-left: 20px; display: grid; gap: 8px; margin-top: 8px; }
.legal a { color: var(--ink); font-weight: 550; }
/* The Terms and Conditions page (src/pages/terms.mjs): the document's own order, set as the privacy page is. */
.legal h3 { font-size: 1.0625rem; font-weight: 600; letter-spacing: var(--trk-sub); line-height: var(--lh-head); margin: 28px 0 8px; scroll-margin-top: calc(var(--nav-h) + 16px); }
.terms__edition { padding: 14px 16px; border-radius: var(--r-m); background: var(--sunken); color: var(--ink-2); max-width: 68ch; margin-bottom: 24px; }
.terms__meta { color: var(--ink-2); }
.legal .terms__status { margin-top: 4px; font-size: .875rem; color: var(--ink-3); }
.terms__company { display: grid; gap: 12px; margin-top: 24px; padding: 20px; border: 1px solid var(--hair-2); border-radius: var(--r-l); max-width: 68ch; }
.legal .terms__company p + p { margin-top: 0; }
.terms__toc { margin-top: 40px; }
.terms__toc ol { list-style: none; padding: 0; display: grid; gap: 20px; }
.terms__toc ol ol { list-style: decimal; padding-left: 22px; gap: 6px; margin-top: 8px; color: var(--ink-3); }
.terms__toc-part { font-weight: 600; color: var(--ink); }
@media (min-width: 760px) { .terms__toc > ol { grid-template-columns: 1fr 1fr; column-gap: 40px; } }
.legal .terms__toc a { font-weight: 450; color: var(--ink-2); }
.terms__part { margin-top: 32px; }
.terms__label { font-size: .75rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); margin: 0 0 4px; padding-top: 28px; border-top: 1px solid var(--hair-2); }
.legal .terms__part h2 { border-top: 0; padding-top: 0; margin-top: 0; }
.terms__note { margin-top: 20px; padding: 16px 20px; border-radius: var(--r-m); background: var(--accent-soft); max-width: 68ch; }
.legal .terms__note p { color: var(--ink); }
.terms__updated { margin-top: 40px; }

.nf { min-height: 58vh; display: grid; align-content: center; }

/* ---- the opening screen: the lockup draws itself once, then gives way to the page ----
   Drawn only when the page head asks for it (html[data-splash]: a first arrival in this browser tab, with
   scripting on). White with the black logo; black with the white logo in the dark theme. Every part is timed
   from the first paint, and the screen takes itself away with its own last animation, so it cannot be left over
   the page. Any press, key or scroll sets data-splash="done", which ends it at once. */
.splash { display: none; }
html[data-splash] .splash { --w: clamp(208px, 30vw, 330px); position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; background: #fff; color: #000; animation: splash-out 300ms ease 1480ms forwards; }
html[data-splash][data-theme="dark"] .splash { background: #000; color: #fff; }
html[data-splash="done"] .splash { animation: splash-out 160ms ease forwards; }
@keyframes splash-out { to { opacity: 0; visibility: hidden; } }
/* The lockup's proportions are the supplied file's, measured against the wordmark's width. */
.splash__logo { display: grid; justify-items: start; width: var(--w); margin-top: -3vh; }
.splash__mark { display: block; width: calc(var(--w) * .8107); margin-left: calc(var(--w) * .1036); overflow: visible; animation: splash-rise 520ms var(--ease) 740ms both; }
.splash__word { display: block; width: 100%; aspect-ratio: 844 / 49; margin-top: calc(var(--w) * .081); background: currentColor; -webkit-mask: url(/images/o2-wordmark.png) center / 100% 100% no-repeat; mask: url(/images/o2-wordmark.png) center / 100% 100% no-repeat; animation: splash-word 440ms var(--ease) 780ms both; }
.splash__dash { display: block; width: calc(var(--w) * .1119); height: max(2px, calc(var(--w) * .0167)); margin: calc(var(--w) * .067) 0 0 calc(var(--w) * .433); background: #0201FD; transform-origin: 50% 50%; animation: splash-dash 300ms var(--ease) 1020ms both; }
/* The ring: two arcs sweep round from its two gaps, turning into place. Then the 2 is drawn from the top of its hook. */
.splash__sweep, .splash__stroke { stroke-dasharray: 1; stroke-dashoffset: 1; }
.splash__sweep { animation: splash-draw 600ms var(--ease) 60ms forwards; }
.splash__stroke { animation: splash-draw 520ms cubic-bezier(.3, .6, .2, 1) 340ms forwards; }
.splash__ring { transform-origin: 50px 50px; animation: splash-turn 660ms var(--ease) 60ms both; }
/* Once both are drawn the mark itself, unmasked, takes their place: the masks are only how it arrives. */
.splash__whole { opacity: 0; animation: splash-show 90ms linear 860ms forwards; }
@keyframes splash-draw { to { stroke-dashoffset: 0; } }
@keyframes splash-turn { from { transform: rotate(-38deg); } }
@keyframes splash-show { to { opacity: 1; } }
@keyframes splash-rise { from { transform: translateY(13%); } }
@keyframes splash-word { from { opacity: 0; clip-path: inset(0 50% 0 50%); } to { opacity: 1; clip-path: inset(0 0 0 0); } }
@keyframes splash-dash { from { transform: scaleX(0); } }
/* Reduced motion: no drawing and nothing that travels. The finished logo, briefly, then a fade. */
@media (prefers-reduced-motion: reduce) {
  html[data-splash] .splash { animation: splash-out 200ms ease 650ms forwards; }
  .splash__mark, .splash__word, .splash__dash, .splash__ring, .splash__sweep, .splash__stroke { animation: none; }
  .splash__sweep, .splash__stroke { stroke-dashoffset: 0; }
  .splash__whole { animation: none; opacity: 1; }
}
@media print { .splash { display: none !important; } }

/* ---- home: two ways in for someone not ready to choose a product (the audit, the adviser) ---- */
.hero__ways { margin-top: 14px; font-size: .9375rem; color: var(--ink-2); max-width: 46ch; }
.hero__ways a { color: var(--ink); font-weight: 550; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--hair-2); }
.hero__ways a:hover { text-decoration-color: currentColor; }

/* ---- reveal on scroll: only ever applied by the script that reveals ------- */
.rv-pre { opacity: 0; transform: translateY(14px); }
.rv-in { transition: opacity var(--t-slow) var(--ease) var(--rv-delay, 0ms), transform var(--t-slow) var(--ease) var(--rv-delay, 0ms); }

/* ---- pointer hover: only where a pointer can hover ------------------------ */
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover { background: var(--ink-hover); }
  .band--dark .btn--primary:hover, .tray .btn--primary:hover { background: #E4E8F0; }
  .btn--ghost:hover { box-shadow: inset 0 0 0 1px var(--ink-3); }
  .btn--quiet:hover { color: var(--ink); box-shadow: inset 0 0 0 1px var(--hair-2); }
  .btn--on-dark:hover { background: rgba(255, 255, 255, .14); }
  .nav__links > a:hover { color: var(--ink); }
  .npanel__list a:hover { background: var(--canvas); }
  .nav__links > a:hover::after { transform: scaleX(1); }
  .lang a:hover { color: var(--ink); }
  .lang--foot a:hover, .foot a:hover { color: var(--on-dark); }
  .link:hover .i, .route:hover .i, .pcard:hover .pcard__link .i, .need__a a:hover .i { transform: translateX(3px); }
  .link:hover .spark .i { transform: none; }
  :is(.btn, .link):not([disabled]):hover .spark { transform: rotate(90deg) scale(1.2); filter: drop-shadow(0 0 5px rgba(139, 92, 246, .5)); }
  :is(.btn, .link):not([disabled]):hover .spark .i { opacity: 0; }
  :is(.btn, .link):not([disabled]):hover .spark::after { opacity: 1; animation: spark-flow 1.8s linear infinite; }
  .pcard:hover, .wcard:hover { box-shadow: var(--shadow-lift); }
  .wcard:hover .wcard__img img { transform: scale(1.03); }
  .route:hover { background: rgba(255, 255, 255, .08); }
  .chip:hover, .radio:hover span { box-shadow: inset 0 0 0 1px var(--ink-3); }
  .chip[aria-pressed="true"]:hover, .radio:hover input:checked + span { box-shadow: none; }
  .drow:hover { box-shadow: 0 0 0 1px var(--hair-2); }
  .crumbs a:hover, .legal a:hover { text-decoration: underline; }
}

/* ---- preferences ---------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; transition-delay: 0ms !important; scroll-behavior: auto !important; }
  .rv-pre { opacity: 1; transform: none; }
  .btn:active, .chip:active, .demo button:active, .route:active { transform: none; }
  .spark, :is(.btn, .link):not([disabled]):is(:hover, :focus-visible) .spark { transform: none; }
  .spinner { animation-duration: 1.4s !important; animation-iteration-count: infinite !important; }
}
@media (prefers-reduced-transparency: reduce) {
  .nav, .nav--scrolled, .nav--open { background: var(--canvas); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .sheet { background: var(--canvas); }
  .tray { background: var(--dark); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  :root { --hair: rgba(17, 23, 34, .4); --hair-2: rgba(17, 23, 34, .6); --ink-2: #2A3342; --ink-3: #3A4455; --ink-4: #4B5668; --hair-dark: rgba(255, 255, 255, .5); }
  :root[data-theme="dark"] { --hair: rgba(255, 255, 255, .42); --hair-2: rgba(255, 255, 255, .62); --ink-2: #E3E8F0; --ink-3: #D2D9E5; --ink-4: #BFC8D6; }
  .nav, .sheet { background: var(--canvas); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: 0 1px 0 var(--ink); }
  .tray { background: var(--dark); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: 0 0 0 1px #fff; }
}
@media print { .nav, .tray, .scrim, .closing { display: none !important; } main { padding-top: 0; } }

/* ---- examples gallery ---- */
/* /examples: fictional businesses with sample data. A card here is not a portfolio card: every one
   carries a "Fictional example" label, and the page says where client work is. The filters are driven
   by data-exg-* on <html> (set before first paint by the script in the page head, see
   src/pages/examples.mjs); the rules that hide a card are generated there, next to that script. */
.exg__filters { display: none; gap: 20px 40px; margin-bottom: 22px; }
html[data-exg] .exg__filters { display: grid; }
.exg__q { font-size: .875rem; font-weight: 550; color: var(--ink-2); margin-bottom: 10px; }
.exg .chip { min-height: 44px; }
.exg__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 20px; min-height: 44px; margin-bottom: 12px; }
.exg__count { font-size: .9375rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
html[data-exg-f] .exg__count:not([data-live]) { visibility: hidden; }  /* filtered link: the count waits for the real number */
.exg__reset { display: none; min-height: 44px; }
html[data-exg-f] .exg__reset { display: inline-flex; }
.exg__gap[data-gap] { display: none; }
.exg__gap { margin: 0 0 14px; max-width: 760px; }
.exg__gap p { margin-top: 8px; }
.exg__near { display: flex; flex-wrap: wrap; gap: 6px 22px; align-items: center; }
.exg__near .link { min-height: 44px; }

.exgrid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); }
.excard { position: relative; display: flex; flex-direction: column; border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); transition: box-shadow var(--t-med) var(--ease); }
.excard__img { margin: 8px 8px 0; border-radius: 21px; overflow: hidden; background: var(--sunken); aspect-ratio: 3 / 2; }
.excard__img img { width: 100%; height: 100%; object-fit: cover; object-position: top; transition: transform 900ms var(--ease); }
.excard__body { display: flex; flex-direction: column; flex: 1; gap: 6px; padding: 16px clamp(16px, 1.8vw, 22px) clamp(10px, 1.2vw, 14px); }
.excard__name { font-size: 1.3125rem; line-height: 1.22; font-weight: 600; letter-spacing: var(--trk-head); margin-top: 8px; }
:lang(th) .excard__name { line-height: 1.4; }
.excard__biz { font-size: .9375rem; font-weight: 550; }
.excard__biz span { font-weight: 400; color: var(--ink-3); }
.excard__task { font-size: .9375rem; color: var(--ink-2); margin-top: 4px; }
.excard__task span { font-weight: 550; color: var(--ink); margin-right: 2px; }
.excard__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 16px; margin-top: auto; padding-top: 8px; }
.excard__open { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; font-weight: 550; text-decoration: none; }
.excard__open .i { color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.excard__open::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-xl); }  /* the whole card opens the example */
.excard__about { position: relative; z-index: 1; display: inline-flex; align-items: center; min-height: 44px; font-size: .875rem; color: var(--ink-3); text-decoration: underline; text-decoration-color: var(--hair-2); text-underline-offset: 3px; }
/* The link fills the card, so the card shows its focus. Browsers without :has() keep the ring on the link. */
.excard:has(.excard__open:focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }
.excard:has(.excard__open:focus-visible) .excard__open { outline: none; }
.tag--example { padding: 4px 10px; border-radius: var(--pill); box-shadow: inset 0 0 0 1px var(--hair-2); color: var(--ink-2); }
.tag--example::before { display: none; }

/* A plate stands where a photograph of a fictional business will go, until the photograph exists
   (exImage in src/build.mjs writes it): a tonal panel in that business's own colours, a small
   photograph mark, the photograph's shape. The colours and the shape arrive on the element (--xp-*,
   a light set and a dark one; aspect-ratio); its name for a screen reader is the photograph's
   alternative text. It is meant to look placed, not missing. */
.x-plate { --_bg: var(--xp-bg, var(--sunken)); --_ink: var(--xp-ink, var(--ink-3)); --_line: var(--xp-line, var(--hair-2)); position: relative; display: grid; place-items: center; width: 100%; background: var(--_bg); color: var(--_ink); }
:root[data-theme="dark"] .x-plate { --_bg: var(--xp-bg-d, var(--sunken)); --_ink: var(--xp-ink-d, var(--ink-3)); --_line: var(--xp-line-d, var(--hair-2)); }
.x-plate::before { content: ""; position: absolute; inset: 10px; border: 1px solid var(--_line); border-radius: 13px; opacity: .55; }  /* a mount line, as round a frame's window */
.x-plate__mark { width: 30px; height: 30px; }
.excard__img .x-plate { height: 100%; }

@media (min-width: 900px) {
  html[data-exg] .exg__filters { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .exg__axis--type { grid-column: 1 / -1; }
}
@media (hover: hover) and (pointer: fine) {
  .excard:hover { box-shadow: var(--shadow-lift); }
  .excard:hover .excard__img img { transform: scale(1.03); }
  .excard:hover .excard__open .i { transform: translateX(3px); }
  .excard__about:hover { color: var(--ink); text-decoration-color: currentColor; }
}
@media (prefers-reduced-motion: reduce) { .excard:hover .excard__img img, .excard:hover .excard__open .i { transform: none; } }
@media (prefers-contrast: more) { .excard { box-shadow: 0 0 0 1px var(--hair-2); } .x-plate::before { opacity: 1; } }
/* On a phone the gallery is a list (Phase 6, page 20): a thumbnail beside the name, the business and the task, so thirty
   examples are about nine screens instead of twenty-three. "Then" (where the task leads) is shown inside the example
   itself, so the card leaves it out here; every card keeps its fictional label, its product and both of its links. */
@media (max-width: 639px) {
  .exgrid { gap: 10px; }
  .excard { display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: start; border-radius: var(--r-l); }
  .excard__img { margin: 10px 0 10px 10px; aspect-ratio: 3 / 4; border-radius: 12px; }
  .excard__body { padding: 10px 14px 4px 12px; gap: 2px; }
  .excard .tags { gap: 4px; }
  .excard__name { font-size: 1.0625rem; margin-top: 4px; }
  .excard__biz, .excard__task { font-size: .875rem; }
  .excard__next { display: none; }
  /* The product is named again by "About …" under the card, and the kind of business by its name: said once here. */
  .excard .tag--product, .excard__biz span { display: none; }
  /* Each filter group is one row that scrolls on its own, inside its labelled group; the page never scrolls sideways. */
  .exg__axis .chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: -16px; padding: 2px 16px 6px; scroll-padding-inline: 16px; -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 24px), transparent 100%); mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 24px), transparent 100%); }
  .exg__axis .chips::-webkit-scrollbar { display: none; }
  .exg__axis .chip { flex: none; }
  /* The rows scroll inside their groups: the grid that holds them must not grow to their full length. */
  html[data-exg] .exg__filters { grid-template-columns: minmax(0, 1fr); }
  .exg__axis { min-width: 0; }
  .excard__actions { padding-top: 2px; gap: 0 12px; }
  .excard__open::after { border-radius: var(--r-l); }
}

/* ---- example components ---- */
/* Doorways from O2's own pages into the examples (src/lib/example-parts.mjs): the teaser in three sizes,
   "See this for your business" (src/js/niche.js) and the curated strip. Everything drawn here is a link
   into an example or a choice between examples; nothing looks pressable that is not. Colours come from
   the tokens, so both themes follow. --xt-1 to --xt-acc exist only so the same parts can sit on a dark
   band; --xt-ink and --xt-sub arrive on a plate from the fictional business's own colours. */
.xt, .nsel, .xstrip { --xt-1: var(--ink); --xt-2: var(--ink-2); --xt-3: var(--ink-3); --xt-hair: var(--hair-2); --xt-acc: var(--accent); min-width: 0; }
.band--dark :is(.xt, .nsel, .xstrip) { --xt-1: var(--on-dark); --xt-2: var(--on-dark-2); --xt-3: var(--on-dark-2); --xt-hair: var(--hair-dark); --xt-acc: var(--on-dark-accent); }
.band--dark .xt--card { --xt-1: var(--ink); --xt-2: var(--ink-2); --xt-3: var(--ink-3); --xt-hair: var(--hair-2); --xt-acc: var(--accent); }

/* The mark every doorway carries. Quiet, and always the same. */
.exmark { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: var(--pill); box-shadow: inset 0 0 0 1px var(--xt-hair, var(--hair-2)); font-size: .8125rem; font-weight: 550; line-height: 1.2; color: var(--xt-2, var(--ink-2)); white-space: nowrap; }
:lang(th) .exmark { line-height: 1.45; }
.exlink { color: inherit; font-weight: 550; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--hair-2); text-decoration-color: color-mix(in srgb, currentColor 34%, transparent); transition: text-decoration-color var(--t-fast) ease; }

/* The teaser. Its picture is the example's screenshot in a plain frame: no window buttons, no address bar. */
.xt { position: relative; color: var(--xt-1); }
.xt__shot { position: relative; display: block; aspect-ratio: 16 / 10; border-radius: var(--r-l); overflow: hidden; background: var(--sunken); color: inherit; text-decoration: none; }
.xt__shot > img, .xt__shot > .x-plate { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
:root[data-theme="dark"] .xt__shot > img { filter: brightness(.9) saturate(.94); }
/* Until the screenshot exists the plate is a title card: the business's name, set in its own ink, the photograph mark moved to a corner. */
.xt__shot--plate > .x-plate { place-items: start; padding: clamp(20px, 7%, 30px); }
.xt__shot--plate .x-plate__mark { width: 22px; height: 22px; opacity: .8; }
.xt__card { position: absolute; inset: auto 0 0; display: grid; gap: 3px; padding: clamp(20px, 7%, 30px); color: var(--xt-ink, var(--ink)); pointer-events: none; }
.xt__card b { font-size: 1.25rem; line-height: 1.15; font-weight: 600; letter-spacing: var(--trk-head); }
.xt__card span { font-size: .8125rem; line-height: 1.4; color: var(--xt-sub, var(--ink-3)); }
:lang(th) .xt__card span { line-height: 1.6; }
:root[data-theme="dark"] .xt__card { color: var(--xt-ink-d, var(--ink)); }
:root[data-theme="dark"] .xt__card span { color: var(--xt-sub-d, var(--ink-3)); }
.xt__tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.xt__product { font-size: .8125rem; font-weight: 550; color: var(--xt-3); }
.xt__label { margin: 0; font-size: 1.3125rem; line-height: 1.22; font-weight: 600; letter-spacing: var(--trk-head); text-wrap: balance; }
:lang(th) .xt__label { line-height: 1.4; }
.xt__biz { font-size: .9375rem; font-weight: 550; }
.xt__biz span { font-weight: 400; color: var(--xt-3); }
.xt__task { font-size: .9375rem; color: var(--xt-2); max-width: 52ch; text-wrap: pretty; }
.xt__task span { font-weight: 550; color: var(--xt-1); margin-right: 2px; }
.xt__in-label { margin-top: 10px; font-size: .8125rem; font-weight: 550; color: var(--xt-3); }
.xt__links { display: grid; width: 100%; border-top: 1px solid var(--xt-hair); }
.xt__links li { border-bottom: 1px solid var(--xt-hair); }
.xt__links a { display: flex; align-items: center; justify-content: space-between; gap: 14px; min-height: 48px; padding-block: 8px; font-size: .9375rem; font-weight: 500; line-height: 1.35; color: var(--xt-1); text-decoration: none; }
:lang(th) .xt__links a { line-height: 1.5; }
.xt__links .i, .xt__open .i, .xt--compact > .i { color: var(--xt-acc); transition: transform var(--t-fast) var(--ease); }
.xt__open { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; font-weight: 550; text-decoration: none; }

/* large: the picture beside the words, nothing around them. It arranges itself by the width it is given. */
.xt--large { container: xt / inline-size; }
.xt--large .xt__in { display: grid; gap: clamp(20px, 5cqi, 32px); }
.xt--large .xt__shot { border-radius: clamp(16px, 4cqi, 24px); box-shadow: var(--shadow-lift); transition: transform var(--t-press) ease-out, box-shadow var(--t-med) var(--ease); }
.xt--large .xt__shot:active { transform: scale(.992); }
.xt--large .xt__card b { font-size: clamp(1.375rem, 5cqi, 2.125rem); }
.xt--large .xt__body { display: grid; gap: 10px; justify-items: start; align-content: start; min-width: 0; }
.xt--large .xt__label { font-size: clamp(1.5rem, 1.2rem + 1.4cqi, 2rem); line-height: 1.16; }
:lang(th) .xt--large .xt__label { line-height: 1.36; }
.xt--large .xt__actions { margin-top: 14px; }
@container xt (min-width: 660px) {
  .xt--large .xt__in { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); align-items: center; gap: clamp(28px, 5cqi, 64px); }
}

/* card: for grids and strips. The open link covers the card; the example's own links sit above it. */
.xt--card { display: flex; flex-direction: column; width: 100%; padding: 8px; border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); transition: box-shadow var(--t-med) var(--ease); }
.band--tint .xt--card { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.xt--card .xt__shot { border-radius: 21px; }
.xt--card .xt__shot > img { transition: transform 900ms var(--ease); }
.xt--card .xt__body { display: flex; flex-direction: column; flex: 1; gap: 6px; padding: 16px clamp(8px, 1.2vw, 14px) 4px; }
.xt--card .xt__label { margin-top: 8px; }
.xt--card .xt__in-label { margin-top: 8px; }
.xt--card .xt__links a { position: relative; z-index: 1; min-height: 44px; font-size: .875rem; }
.xt--card .xt__actions { margin-top: auto; padding-top: 6px; }
.xt--card .xt__open::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-xl); }
.xt--card:has(.xt__open:focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }
.xt--card:has(.xt__open:focus-visible) .xt__open { outline: none; }

/* compact: one row, one link. */
.xt--compact { display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; align-items: center; gap: 14px; padding: 10px 16px 10px 10px; border-radius: var(--r-l); box-shadow: inset 0 0 0 1px var(--xt-hair); text-decoration: none; transition: transform var(--t-press) ease-out, box-shadow var(--t-fast) ease; }
.xt--compact:active { transform: scale(.985); }
.xt--compact .xt__shot { border-radius: 10px; }
.xt--compact .x-plate::before { inset: 5px; border-radius: 6px; }
.xt--compact .x-plate__mark { width: 20px; height: 20px; }
.xt--compact .xt__body { display: grid; gap: 2px; justify-items: start; min-width: 0; }
.xt--compact .xt__label { font-size: 1rem; line-height: 1.3; letter-spacing: var(--trk-sub); }
:lang(th) .xt--compact .xt__label { line-height: 1.5; }
.xt--compact .xt__biz { font-size: .8125rem; font-weight: 400; color: var(--xt-2); }
.xt--compact .xt__tags { margin-top: 5px; }
.xt--compact .exmark { padding: 2px 8px; font-size: .75rem; }
@media (max-width: 419px) { .xt--compact { grid-template-columns: 72px minmax(0, 1fr) auto; gap: 12px; padding-right: 12px; } }

/* "See this for your business". Without scripts the choices are links and every panel is listed under
   its heading. Once a choice is in place (data-on) one panel shows and its heading is for screen readers. */
.nsel { display: grid; gap: clamp(18px, 2.4vw, 26px); color: var(--xt-1); }
.nsel__head { display: grid; gap: 10px; }
.nsel__h, .nsel__gap .h3, .xstrip__head > :first-child { margin: 0; }  /* a label may be an h5 or h6, which the base styles leave with their margins */
.nsel__h.h2 { max-width: 22ch; }
.nsel__sub { max-width: 58ch; color: var(--xt-2); text-wrap: pretty; }
.nsel__tabs { display: flex; flex-wrap: wrap; gap: 8px; }
.nsel__tab { min-height: 44px; }
.nsel__tab.is-on { background: var(--ink); box-shadow: none; color: var(--on-ink); }
.band--dark .nsel__tab { background: rgba(255, 255, 255, .07); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2); color: var(--on-dark); }
.band--dark .nsel__tab.is-on { background: #fff; box-shadow: none; color: #111722; }
.nsel__panels { display: grid; gap: clamp(28px, 4vw, 44px); min-width: 0; }
.nsel__panel { position: relative; min-width: 0; scroll-margin-top: calc(var(--nav-h) + 16px); }
.nsel__ph { margin-bottom: 16px; padding-top: 18px; border-top: 1px solid var(--xt-hair); font-size: 1.0625rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); }
.nsel[data-on] .nsel__ph { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* The change of panel: a short fade in, from the first real change on. Nothing waits for it. */
.nsel[data-live] .nsel__panel:not([hidden]) { animation: nsel-in var(--t-fast) ease-out; }
@keyframes nsel-in { from { opacity: 0; } }
/* A limit said beside an example (a hotel is served through its restaurant): marked with the site's small accent dot,
   as its labels are, not with a rule down one side. */
.nsel__bound { position: relative; max-width: 68ch; margin-bottom: 18px; padding-left: 16px; font-size: .9375rem; color: var(--xt-2); }
.nsel__bound::before { content: ""; position: absolute; left: 1px; top: .62em; top: calc(.5lh - 3px); width: 6px; height: 6px; border-radius: 50%; background: var(--xt-acc); }
.nsel__note, .nsel__gap { display: grid; gap: 8px; max-width: 760px; padding: 18px 20px; border-radius: var(--r-m); box-shadow: inset 0 0 0 1px var(--xt-hair); font-size: .9375rem; color: var(--xt-2); }
.nsel__note b, .nsel__gap .h3 { color: var(--xt-1); font-weight: 600; }
.nsel__near { display: flex; flex-wrap: wrap; align-items: center; gap: 0 20px; font-size: .9375rem; color: var(--xt-2); }
.nsel__near .link { min-height: 44px; color: var(--xt-1); }
.nsel__near .link .i { color: var(--xt-acc); }
.nsel__also { margin-top: 18px; }

/* The curated strip: a row that scrolls sideways on a phone or a tablet, out to the screen edge (so it
   belongs directly inside a .wrap), with the next card showing; a grid from 1000px. Six cards at most. */
.xstrip__list { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(min(78vw, 300px), 1fr); gap: 14px; margin: -6px calc(var(--gutter) * -1) -26px; padding: 6px var(--gutter) 26px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); scrollbar-width: none; }
.xstrip__list::-webkit-scrollbar { display: none; }
.xstrip__list > li { display: flex; min-width: 0; scroll-snap-align: start; }
.xstrip__foot { margin-top: 18px; }
.xstrip .link { min-height: 44px; }
@media (min-width: 1000px) {
  .xstrip__list { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(6, minmax(0, 1fr)); margin: 0; padding: 0; overflow: visible; }
  .xstrip__list > li { grid-column: span 2; }
  .xstrip[data-n="2"] .xstrip__list > li, .xstrip[data-n="4"] .xstrip__list > li, .xstrip[data-n="5"] .xstrip__list > li:nth-child(n+4) { grid-column: span 3; }
}
@media (min-width: 1180px) {
  .xstrip[data-n="4"] .xstrip__list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .xstrip[data-n="4"] .xstrip__list > li { grid-column: auto; }
}

@media (hover: hover) and (pointer: fine) {
  .xt--card:hover { box-shadow: var(--shadow-lift); }
  .xt--card:hover .xt__shot > img { transform: scale(1.03); }
  .xt--card:hover .xt__open .i, .xt__links a:hover .i, .xt--compact:hover > .i { transform: translateX(3px); }
  .xt--large .xt__shot:hover { box-shadow: var(--shadow-float); }
  .xt--compact:hover { box-shadow: inset 0 0 0 1px var(--xt-3); }
  .nsel__tab.is-on:hover { box-shadow: none; }
  .band--dark .nsel__tab:not(.is-on):hover { background: rgba(255, 255, 255, .14); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2); }
  .exlink:hover { text-decoration-color: currentColor; }
}
@media (prefers-reduced-motion: reduce) {
  .xt--card:hover .xt__shot > img, .xt--card:hover .xt__open .i, .xt__links a:hover .i, .xt--compact:hover > .i, .xt--large .xt__shot:active, .xt--compact:active { transform: none; }
}
@media (prefers-contrast: more) { .xt--card { box-shadow: 0 0 0 1px var(--hair-2); } }

/* ---- finder and contact ---- */
/* The header with Examples in it, the finder's "Try this for your business", the enquiry context on the
   contact form, and the small changes to Work and About. No new colours: everything is drawn from the
   tokens at the top of the file. */

/* Header. Five places and one tool: the finder link sits at the far end of the row, beside the language
   switch, so it reads as a utility and the five keep their rhythm. */
.nav__links > a { white-space: nowrap; }
.nav__find { gap: 7px; margin-left: auto; }
.nav__links > .nav__find::after { left: 35px; }
.nav__find:focus-visible .spark { transform: rotate(90deg) scale(1.2); filter: drop-shadow(0 0 5px rgba(139, 92, 246, .5)); }
.nav__find:focus-visible .spark .i { opacity: 0; }
.nav__find:focus-visible .spark::after { opacity: 1; animation: spark-flow 1.8s linear infinite; }
/* O2 Engine (src/content/site.mjs ENGINE): the O2 mark and the word "Engine", one lockup. The row has room for it
   only if it closes up: the links a little tighter, and on a small laptop the mark alone (its name is still read
   out); the word beside it from 1280 px (measured 19 October 2026, English and Thai). */
.nav__engine, .foot__engine { gap: 6px; color: var(--ink); font-weight: 600; }
/* With no adviser link before it (the home page), the engine's link takes the adviser's place at the end of the list. */
.nav__links:not(:has(> .nav__find)) > .nav__engine { margin-left: auto; }
/* "(beta)" beside the name, quieter than it. */
.beta { font-weight: 400; color: var(--ink-2); white-space: nowrap; }
.foot__engine { display: inline-flex; align-items: center; }
.nav__engine-mark { width: 21px; height: 18px; flex: none; color: currentColor; }
.sheet__link--engine .nav__engine-mark { width: 26px; height: 22px; }
.foot__engine .nav__engine-mark { width: 18px; height: 15px; }
.nav__links > .nav__engine::after { left: 36px; }
@media (min-width: 67.5em) {
  .nav__links:has(> .nav__engine) > a { padding-inline: 9px; }
  .nav__links:has(> .nav__engine) > a::after { left: 9px; right: 9px; }
  .nav__links:has(> .nav__engine) > .nav__find::after { left: 32px; }
  .nav__links > .nav__engine::after { left: 9px; }
}
@media (min-width: 67.5em) and (max-width: 79.99em) {
  .nav__engine-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .nav__engine .beta { display: none; }
}
@media (min-width: 80em) { .nav__links > .nav__engine::after { left: 36px; } }
.sheet__link--find { gap: 10px; }
.sheet__link--find .spark { width: 18px; height: 18px; }
.sheet__link--find .spark .i { width: 18px; height: 18px; }
/* A small laptop: six links, the language switch, the theme switch and the button share about a
   thousand pixels, in Thai as in English. The row closes up a little so that nothing touches. */
@media (min-width: 67.5em) and (max-width: 79.99em) {
  .nav__bar { gap: 16px; }
  .nav__end { gap: 10px; }
  .nav__links { gap: 0; }
  .nav__links > a { padding-inline: 9px; font-size: .90625rem; }
  .nav__links > a::after { left: 9px; right: 9px; }
  .nav__links > .nav__find::after { left: 32px; }
}
@media (hover: hover) and (pointer: fine) {
  .nav__find:hover .spark { transform: rotate(90deg) scale(1.2); filter: drop-shadow(0 0 5px rgba(139, 92, 246, .5)); }
  .nav__find:hover .spark .i { opacity: 0; }
  .nav__find:hover .spark::after { opacity: 1; animation: spark-flow 1.8s linear infinite; }
}
@media (prefers-reduced-motion: reduce) {
  .nav__find:is(:hover, :focus-visible) .spark { transform: none; }
}

/* Finder results. Under the product's name, what it is; under the reasons, an example to open. */
.rec__sub { margin-top: -8px; font-size: .9375rem; font-weight: 500; color: var(--ink-3); }
.rec__try { display: grid; gap: 10px; padding-top: 16px; border-top: 1px solid var(--hair); }
.rec__try-h { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.rec__try-why { font-size: .9375rem; color: var(--ink-2); max-width: 60ch; text-wrap: pretty; }
.rec__try-note { font-size: .8125rem; line-height: 1.5; color: var(--ink-3); }
:lang(th) .rec__try-note { line-height: 1.68; }
.rec__try .xt--compact { background: var(--canvas); }
.qbox > .rec__try { padding-top: 0; border-top: 0; }

/* Finder: what was understood. Three short lists (what there is, what is wanted, what is not needed),
   each item with a way to take it out, and under them every topic in a list that can be set by hand. */
.und__groups { display: grid; gap: 12px; margin: 2px 0 4px; }
.und__g { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }
.und__g dt { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.sum .und__list { display: flex; flex-wrap: wrap; gap: 6px; }
.sum .und__list li { padding-left: 0; }
.sum .und__list li::before { display: none; }
.und__it { display: inline-flex; align-items: center; min-height: 36px; max-width: 100%; border-radius: var(--r-s); background: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair); color: var(--ink); }
.und__t { padding: 6px 12px; line-height: 1.4; }
:lang(th) .und__t { line-height: 1.6; }
.und__t:has(+ .und__x) { padding-right: 2px; }
.und__x { position: relative; display: inline-grid; place-items: center; flex: none; width: 34px; height: 36px; border: 0; border-radius: var(--r-s); background: none; color: var(--ink-3); transition: transform var(--t-press) ease-out, color var(--t-fast) ease; }
.und__x::after { content: ""; position: absolute; inset: -4px -5px; }
.und__x:active { transform: scale(.9); }
.und__x .i { width: 13px; height: 13px; }
.sum .und__assumed { margin-bottom: 2px; }
.und__more { margin-top: 10px; }
.und__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); gap: 12px 14px; margin-top: 12px; padding-bottom: 4px; }
.und__grid .fbiz__field { max-width: none; }
@media (min-width: 560px) {
  .und__g { grid-template-columns: 8.75rem minmax(0, 1fr); gap: 12px; align-items: start; }
  .und__g dt { padding-top: 9px; }
}
/* A finger: the quiet actions in a result are as tall as the rest. */
@media (pointer: coarse) { .results .link, .results .btn--s { min-height: 44px; } }
/* A correction is worked out again with the result still on screen: it dims, it does not vanish. */
.results.is-updating { opacity: .6; transition: opacity 160ms ease-out; }
.results.is-settled :is(.rec, .qbox) { animation: none; }
/* Three kinds of answer. Recommended carries the accent; what has to be assessed and what is optional do not. */
.rec--assess { box-shadow: inset 0 0 0 1px var(--hair-2), var(--shadow-card); }
.rec--later { background: none; box-shadow: inset 0 0 0 1px var(--hair-2); }
.rec--later .rec__name { font-size: 1.25rem; }
.rec__note a { font-weight: 550; }
.rec__facts { display: grid; gap: 12px; padding-top: 16px; border-top: 1px solid var(--hair); }
.rec__facts > div { display: grid; gap: 3px; }
.rec__facts dt { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.rec__facts dd { font-size: .875rem; line-height: 1.55; color: var(--ink-2); max-width: 64ch; text-wrap: pretty; }
:lang(th) .rec__facts dd { line-height: 1.72; }
.chip--quiet { background: none; box-shadow: none; color: var(--ink-2); text-decoration: underline; text-decoration-color: var(--hair-2); text-underline-offset: 4px; }
/* The plan, set out for review before it is carried to the contact form. */
.plan__list { display: grid; }
.plan__list > div { display: grid; gap: 4px; padding: 12px 0; border-top: 1px solid var(--hair); }
.plan__list > div:last-child { border-bottom: 1px solid var(--hair); }
.plan__list dt { font-size: .8125rem; font-weight: 550; line-height: 1.5; color: var(--ink-3); }
.plan__list dd { display: grid; gap: 4px; font-size: .9375rem; color: var(--ink); min-width: 0; }
.plan__text { quotes: "\201C" "\201D"; color: var(--ink-2); overflow-wrap: anywhere; }
.plan__note { font-size: .8125rem; line-height: 1.5; color: var(--ink-3); }
.plan #plan-h:focus { outline: none; }
.sum.und > h2:first-child { font-size: 1rem; font-weight: 600; line-height: 1.35; color: var(--ink); }
.und #und-h:focus { outline: none; }
.und #und-h:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
@media (min-width: 560px) { .plan__list > div { grid-template-columns: 10.5rem minmax(0, 1fr); gap: 16px; } }
@media (hover: hover) and (pointer: fine) {
  .start__h a:hover .i { transform: translateX(3px); }
  .start__add li a:hover, .closing__direct a:hover { text-decoration: underline; text-underline-offset: 3px; }
  .und__x:hover { color: var(--ink); }
  .chip--quiet:hover { color: var(--ink); text-decoration-color: currentColor; }
}
@media (prefers-reduced-motion: reduce) { .results.is-updating { transition: none; } }

/* The contact form's Send button is off until its script has started. This line under it says why and
   gives the direct ways to reach the studio. It takes no room and is not read out while the script is
   only on its way; it appears after four seconds if the script never starts, and at once where
   scripting is off. */
.late { visibility: hidden; max-height: 0; margin: 0; padding-block: 0; overflow: hidden; animation: late 1ms linear 4s forwards; }
@keyframes late { to { visibility: visible; max-height: 30em; margin-top: 16px; padding-block: 15px; } }
@media (scripting: none) { .late { visibility: visible; max-height: none; margin-top: 16px; padding-block: 15px; animation: none; } }
/* The business type the examples are chosen by: a suggestion read from the description, in a control the
   visitor can change. A native select: one line, familiar on a phone, and it says its value aloud. */
.fbiz { display: grid; gap: 8px; margin-top: 8px; padding-top: 14px; border-top: 1px solid var(--hair); }
.fbiz__row { display: flex; flex-wrap: wrap; gap: 12px 16px; }
.fbiz__field { display: grid; gap: 6px; flex: 1 1 200px; min-width: 0; max-width: 320px; }
.fbiz__label { font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.fbiz__select {
  -webkit-appearance: none; appearance: none; width: 100%; min-height: 44px; padding: 0 40px 0 14px; border: 0; border-radius: var(--r-s);
  background-color: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair-2); font-size: .9375rem; font-weight: 500; line-height: 1.3; text-overflow: ellipsis; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(-45deg, transparent 50%, var(--ink-3) 50%);
  background-size: 6px 6px; background-repeat: no-repeat; background-position: right 19px top 50%, right 13px top 50%;
  transition: box-shadow var(--t-fast) ease;
}
.fbiz__select:focus-visible { outline: none; box-shadow: inset 0 0 0 1.5px var(--accent), 0 0 0 4px var(--focus-halo); }
.fbiz__hint { font-size: .8125rem; line-height: 1.5; color: var(--ink-3); }
:lang(th) .fbiz__hint { line-height: 1.68; }
.alert > p + .actions { margin-top: 12px; }
@media (hover: hover) and (pointer: fine) {
  .fbiz__select:hover { box-shadow: inset 0 0 0 1px var(--ink-3); }
}

/* Contact: what an example handed over. A quiet inset at the top of the form, so a visitor who pressed
   "Discuss this setup" sees at once what came with them, and can change or remove each part of it. */
.ctx { display: grid; gap: 14px; margin-bottom: 26px; padding: 18px 20px 16px; border-radius: var(--r-l); background: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair); }
.ctx__h { font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.ctx__items { display: grid; }
.ctx__item { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 4px 12px; padding: 10px 0; border-top: 1px solid var(--hair); }
.ctx__item:last-child { border-bottom: 1px solid var(--hair); }
.ctx__what { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-width: 0; }
.ctx__name { font-size: .9375rem; }
.ctx__name b { font-weight: 600; }
.ctx__name span { color: var(--ink-2); }
.ctx__product { grid-column: 1; font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.ctx__x { grid-column: 2; grid-row: 1 / span 2; display: inline-grid; place-items: center; width: 44px; height: 44px; margin-right: -10px; border: 0; border-radius: 50%; background: none; color: var(--ink-3); transition: transform var(--t-press) ease-out, background-color var(--t-fast) ease, color var(--t-fast) ease; }
.ctx__x:active { transform: scale(.94); }
.ctx__biz { max-width: 340px; }
.ctx .fbiz__select { background-color: var(--surface); }
.ctx__note, .ctx__also { font-size: .8125rem; line-height: 1.5; color: var(--ink-3); max-width: 62ch; }
:lang(th) :is(.ctx__note, .ctx__also) { line-height: 1.68; }
.ctx__also b { font-weight: 550; color: var(--ink-2); }
.ctx__acts { display: flex; flex-wrap: wrap; gap: 6px 20px; }
.ctx__acts .link { min-height: 44px; font-size: .9375rem; }
/* The plan a visitor reviewed in the finder, at the top of the form: the same lines they confirmed. */
.ctx__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ctx__top .link { min-height: 44px; font-size: .875rem; }
.ctx--plan .plan__list > div:first-child { border-top: 0; padding-top: 0; }
.ctx--plan { gap: 10px; }
.ctx--plan .offer { margin-top: 2px; }
/* A product chip with two names: what it is, then its catalogue name, smaller. */
.radio--named small { margin-left: 8px; font-size: .75rem; font-weight: 500; color: var(--ink-3); }
.radio--named input:checked + span small { color: inherit; opacity: .72; }
.radio--named span { height: auto; min-height: 42px; padding-block: 8px; flex-wrap: wrap; row-gap: 0; text-align: left; }
/* A sentence the example offers that the summary does not hold: shown, with one button to add it. */
.offer { display: grid; gap: 10px; justify-items: start; margin-top: 12px; padding: 16px 18px; border-radius: var(--r-m); background: var(--accent-soft); color: var(--alert-info); }
.field + .offer { margin-top: 12px; }
.offer + .fieldset, .offer + .field { margin-top: 20px; }
.offer__h { font-size: .8125rem; font-weight: 550; }
.offer .btn { min-height: 44px; }
.offer__text { font-size: .9375rem; white-space: pre-line; max-width: 62ch; }
@media (hover: hover) and (pointer: fine) {
  .ctx__x:hover { background: rgba(var(--ink-rgb), .06); color: var(--ink); }
}
@media (prefers-reduced-motion: reduce) { .ctx__x:active { transform: none; } }

/* Work. A project card answers the pointer only when the card itself leads somewhere. Where there is a
   case study, its link covers the card, so the picture is a way in; a card with only an outside address,
   or with none, keeps still, and its picture promises nothing. Each picture sits in a hairline, so a
   pale screenshot does not run into the card. */
[data-page="work"] .wcard { position: relative; }
[data-page="work"] .wcard__img { position: relative; }
[data-page="work"] .wcard__img::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--hair); pointer-events: none; }
[data-page="work"] .wcard__links a:not([target])::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-xl); }
[data-page="work"] .wcard__links a[target] { position: relative; z-index: 1; }
[data-page="work"] .wcard:has(.wcard__links a:not([target]):focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }
[data-page="work"] .wcard:has(.wcard__links a:not([target]):focus-visible) .wcard__links a:not([target]) { outline: none; }
.work__apart { margin-top: calc(var(--band) * -.45); padding-bottom: var(--band); }
.work__apart p { max-width: 68ch; padding-top: 22px; border-top: 1px solid var(--hair-2); font-size: .9375rem; color: var(--ink-2); }
.work__apart .link { display: flex; width: fit-content; min-height: 44px; margin-top: 4px; }
@media (hover: hover) and (pointer: fine) {
  [data-page="work"] .wcard:not(:has(.wcard__links a:not([target]))):hover { box-shadow: var(--shadow-card); }
  [data-page="work"] .wcard:not(:has(.wcard__links a:not([target]))):hover .wcard__img img { transform: none; }
}
/* (finder and contact: end) */

/* ---- product pages ---- */
/* /products/<product> (src/pages/product.mjs). The opening and the journey are under "product detail"
   above; this block holds what the page gained with the examples: the drawing beside the opening, the
   "On this page" bar, the example section with the short scope beside it, and the action under the full
   scope. Nothing drawn here can be pressed unless it is a link. */
main { --pnav-h: 48px; }  /* the height of the "On this page" bar, for the bar and for the sections it links to (the industry pages use the same bar) */

/* The drawing beside the opening (FIGURE in product.mjs): the product's shape of work in a few plain
   forms. A drawing, not a preview: no pointer, no hover, hidden from assistive technology. On a phone the
   example just below is the page's picture, so the drawing waits for a wider screen, unless there is no
   example to show (.pd--alone). */
.pd__fig { position: relative; display: none; width: 100%; max-width: 480px; min-width: 0; justify-self: end; pointer-events: none; user-select: none; -webkit-user-select: none; }
.pd--alone .pd__fig { display: block; justify-self: start; }
.pd__fig::before { content: ""; position: absolute; z-index: 0; width: 92%; aspect-ratio: 1; left: 14%; top: 50%; translate: 0 -50%; border-radius: 50%; border: 1.5px solid rgba(var(--glow-rgb), .2); -webkit-mask: conic-gradient(from 22deg, #000 0 166deg, transparent 166deg 180deg, #000 180deg 346deg, transparent 346deg 360deg); mask: conic-gradient(from 22deg, #000 0 166deg, transparent 166deg 180deg, #000 180deg 346deg, transparent 346deg 360deg); }
.pfig { position: relative; z-index: 1; display: block; width: 100%; height: auto; overflow: visible; }
.pf-sh { filter: drop-shadow(0 18px 26px rgba(var(--shade-rgb), .1)); }
:root[data-theme="dark"] .pf-sh { filter: drop-shadow(0 18px 28px rgba(var(--shade-rgb), .5)); }
.pf-s { fill: var(--surface); stroke: var(--hair-2); }
.pf-m { fill: var(--sunken); }
.pf-dim { opacity: .5; }
.pf-k { fill: var(--ink); }
.pf-a { fill: var(--accent); }
.pf-as { fill: var(--accent-soft); }
.pf-bar { fill: var(--bar); }
.pf-h, .pf-o2 { fill: none; stroke: var(--hair-2); }
.pf-o { fill: none; stroke: var(--ink-3); stroke-width: 1.5; }
.pf-l { fill: none; stroke: var(--ink-2); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.pf-on { fill: none; stroke: var(--on-accent); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.pf-d { fill: none; stroke: var(--ink-4); stroke-width: 2; stroke-linecap: round; stroke-dasharray: .1 7; }
.pf-t { fill: var(--ink-2); font: 600 13px/1 var(--font); }
@media (min-width: 720px) {
  .pd__fig { display: block; }
  .pd__in--fig { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
  .pd--alone .pd__fig { justify-self: end; }
}
@media (min-width: 1000px) { .pd__in--fig { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

/* "On this page": a slim bar that starts under the opening and then stays under the site header. Plain
   links to sections of this page; product.js marks the one being read. Four short words fit a phone; if
   the text is enlarged the row scrolls sideways instead of wrapping or pushing the page wide. */
.pnav { position: sticky; top: var(--nav-h); z-index: 60; background: rgba(var(--canvas-rgb), .9); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); box-shadow: 0 1px 0 var(--hair), 0 -1px 0 var(--hair); }
.pnav__list { display: flex; gap: clamp(0px, 1.4vw, 18px); height: var(--pnav-h); margin-inline: -10px; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
.pnav__list::-webkit-scrollbar { display: none; }
.pnav__list li { display: flex; flex: none; }
.pnav a { position: relative; display: inline-flex; align-items: center; min-width: 44px; padding: 0 10px; font-size: .9375rem; font-weight: 500; color: var(--ink-3); text-decoration: none; white-space: nowrap; transition: color var(--t-fast) ease; }
.pnav a::after { content: ""; position: absolute; left: 10px; right: 10px; bottom: 0; height: 2px; border-radius: 1px 1px 0 0; background: var(--ink); transform: scaleX(0); transform-origin: left; transition: transform var(--t-fast) var(--ease); }
.pnav a[aria-current] { color: var(--ink); }
.pnav a[aria-current]::after { transform: scaleX(1); }
.pnav a:focus-visible { outline-offset: -3px; }
.pnav__s { display: none; }
@media (max-width: 479px) {
  .pnav a { font-size: .875rem; }
  .pnav__l { display: none; }
  .pnav__s { display: inline; }
}
@media (max-width: 359px) {
  .pnav__list { gap: 0; margin-inline: -5px; }
  .pnav a { padding-inline: 5px; }
  .pnav a::after { left: 5px; right: 5px; }
}
/* A section the bar links to stops just under it: any section with an id that follows the bar, on any page that
   has one. (html already keeps the site header clear, with 16px to spare.) */
.pnav ~ section[id], .pd-sec { scroll-margin-top: calc(var(--pnav-h) - 16px); }
/* If the row has had to scroll, its far edge fades while there is more to come (product.js sets data-more). */
.pnav__list[data-more] { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 40px), transparent); }
@media (max-height: 480px) { .pnav { position: static; } .pnav ~ section[id], .pd-sec { scroll-margin-top: 0; } }

/* The example section: the selector, then the short scope at reading size, close to "Open full example". */
.pd-try { padding-top: clamp(34px, 3.6vw, 48px); }
.pd-near { display: grid; gap: 20px; margin-top: clamp(30px, 4vw, 52px); padding-top: clamp(22px, 2.6vw, 30px); border-top: 1px solid var(--hair-2); }
.pd-near__lead { max-width: 70ch; color: var(--ink-2); text-wrap: pretty; }
.pd-near__cols { display: grid; gap: 24px clamp(32px, 5vw, 80px); }
.pd-near__h { margin-bottom: 12px; font-size: 1.0625rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); }
:lang(th) .pd-near__h { line-height: 1.5; }
.pd-near__more { display: flex; flex-wrap: wrap; gap: 0 28px; }
.pd-near__more .link { min-height: 44px; }
@media (min-width: 760px) { .pd-near__cols { grid-template-columns: 1fr 1fr; } }
/* Where the opening shows the example's picture, this section holds its details: on a wide screen they sit
   beside the short version of the scope, which is read with them. */
@media (min-width: 1000px) {
  .pd-try--text > .wrap { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: clamp(32px, 5vw, 72px); align-items: start; }
  .pd-try--text .pd-near { margin-top: 0; padding: clamp(20px, 2.4vw, 30px); border: 0; border-radius: var(--r-xl); background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
  .pd-try--text .pd-near__cols { grid-template-columns: minmax(0, 1fr); gap: 20px; }
}
/* What is confirmed for each project: an open ring where an included line has a tick, so the two lists differ by shape, not by colour. */
.pd-open { display: grid; gap: 10px; }
.pd-open li { position: relative; padding-left: 28px; }
.pd-open li::before { content: ""; position: absolute; left: 4px; top: .56em; width: 9px; height: 9px; border-radius: 50%; box-shadow: inset 0 0 0 1.75px var(--ink-4); }
:lang(th) .pd-open li::before { top: .74em; }

/* Under the full scope: the sentence that says how a project is scoped, at reading size, with the action it qualifies. */
.pd-scope__sub { margin-top: 28px; }
.pd-scope__ask { display: grid; gap: 18px; margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--hair-2); }
.pd-scope__ask p { max-width: 54ch; color: var(--ink-2); text-wrap: pretty; }
.pd-whole { white-space: nowrap; }

@media (hover: hover) and (pointer: fine) { .pnav a:hover { color: var(--ink); } }
@media (prefers-reduced-transparency: reduce) { .pnav { background: var(--canvas); -webkit-backdrop-filter: none; backdrop-filter: none; } }
@media (prefers-contrast: more) { .pnav { background: var(--canvas); -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: 0 1px 0 var(--ink); } .pf-s, .pf-h, .pf-o2 { stroke: var(--ink-3); } }
@media print { .pnav { display: none; } }
/* (product pages: end) */

/* ---- home and catalogue ---- */
/* The home page (src/pages/home.mjs), the product stage and the catalogue's card (src/lib/parts.mjs),
   and /products with its comparison (src/pages/products.mjs). Written against the tokens, so both
   themes follow. Nothing drawn here is a control unless it is a link, a button or a checkbox. */

/* A product's picture: the screenshot of the example that stands for it (a title card in that
   business's colours until the file exists), a still of the chat for AI LINE Assistant, or the
   product's own plate. A picture, never a control: no hover, no pointer. */
.pshot { position: relative; display: block; aspect-ratio: 16 / 10; overflow: hidden; border-radius: var(--r-m); background: var(--sunken); container-type: inline-size; }
.pshot::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--hair); pointer-events: none; }
.pshot > img, .pshot > .x-plate { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
:root[data-theme="dark"] .pshot > img { filter: brightness(.9) saturate(.94); }
.pshot--plate > .x-plate { place-items: start; padding: clamp(14px, 8cqi, 28px); }
.pshot--plate .x-plate__mark { width: 20px; height: 20px; opacity: .8; }
.pshot__card { position: absolute; inset: auto 0 0; display: grid; gap: 2px; padding: clamp(14px, 8cqi, 28px); color: var(--ps-ink, var(--ink)); }
.pshot__card b { font-size: clamp(1.0625rem, 6cqi, 1.5rem); line-height: 1.15; font-weight: 600; letter-spacing: var(--trk-head); }
.pshot__card span { font-size: .8125rem; line-height: 1.4; color: var(--ps-sub, var(--ink-3)); }
:lang(th) .pshot__card b { line-height: 1.36; }
:lang(th) .pshot__card span { line-height: 1.6; }
:root[data-theme="dark"] .pshot__card { color: var(--ps-ink-d, var(--ink)); }
:root[data-theme="dark"] .pshot__card span { color: var(--ps-sub-d, var(--ink-3)); }
.pshot--own { color: var(--ink-2); }
.pshot--own > .glyph { position: absolute; left: clamp(14px, 8cqi, 28px); top: clamp(14px, 8cqi, 28px); width: 30px; height: 30px; }
.pshot--own .pshot__card { color: var(--ink); }
.pshot--chat { display: grid; align-items: end; }
.chatpic { display: grid; gap: 6px; padding: clamp(12px, 6cqi, 22px); font-size: .8125rem; line-height: 1.35; color: var(--ink); }
:lang(th) .chatpic { line-height: 1.5; }
.chatpic__msg { justify-self: start; max-width: 88%; padding: 7px 11px; border-radius: 14px 14px 14px 5px; background: var(--surface); box-shadow: 0 0 0 1px var(--hair); }
.chatpic__msg--me { justify-self: end; border-radius: 14px 14px 5px 14px; background: var(--accent-soft); box-shadow: none; }
.chatpic__src { padding-left: 4px; font-size: .6875rem; color: var(--ink-3); }

/* The hero. The scene is tall (a picture and what to try), so the words start at the top beside it
   and stay on the first screen of a short laptop; they are no longer centred against it. */
@media (min-width: 1000px) {
  .hero__in { align-items: start; }
  .hero__copy { padding-top: clamp(12px, 6vh, 64px); }
}


/* The scripted chat: where a reply points to a page, the link is drawn as part of the message and
   labelled a sample. It is not a control and does not look like one. */
/* The scripted conversation: a choice of business above the chat, the note staff would see at the
   hand-over, and under it what is scripted, what was approved and where the assistant stops. */
.dchat__pick { display: grid; gap: 8px; }
.dchat__tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.dchat__tabs .chip { min-height: 36px; }
.dchat__tabs .chip[aria-pressed="true"] { background: var(--ink); box-shadow: none; color: var(--on-ink); }
.demo--convo { gap: 12px; }
.demo--convo .dpane { flex: none; }
.dstaff { display: grid; gap: 10px; padding: 14px 16px; border-radius: 14px; background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair-2); animation: pane var(--t-med) var(--ease); }
.dstaff[hidden] { display: none; }
.dstaff__h { font-size: .8125rem; font-weight: 600; color: var(--ink); }
.dstaff dl { display: grid; gap: 8px; }
.dstaff dl > div { display: grid; gap: 1px; }
.dstaff dt, .dfacts dt { font-size: .75rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.dstaff dd { font-size: .875rem; line-height: 1.5; }
.dstaff__hours { padding-top: 10px; border-top: 1px solid var(--hair); font-size: .8125rem; line-height: 1.5; color: var(--ink-3); }
.dfacts { display: grid; gap: 12px; margin-top: 4px; padding-top: 14px; border-top: 1px solid var(--hair-2); }
.dfacts dl > div { display: grid; gap: 2px; }
.dfacts__mine { display: grid; gap: 12px; }
.dfacts__mine[hidden] { display: none; }
.dfacts dd { font-size: .875rem; line-height: 1.5; color: var(--ink-2); }
.dfacts ul { display: grid; gap: 3px; }
.dfacts li { position: relative; padding-left: 14px; }
.dfacts li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 4px; height: 4px; border-radius: 50%; background: var(--ink-4); }
:lang(th) :is(.dstaff dd, .dfacts dd, .dstaff__hours) { line-height: 1.7; }
@media (pointer: coarse) { .dchat__tabs .chip { min-height: 44px; } .demo--convo .dlink { min-height: 44px; } }
/* The page a customer would be sent, inside the reply: a small outlined card, as a chat shows a link. */
.dmsg__link { display: grid; gap: 1px; width: fit-content; margin-top: 8px; padding: 6px 10px; border-radius: 10px; box-shadow: inset 0 0 0 1px var(--hair-2); font-size: .8125rem; font-weight: 550; }
.dmsg__link span { font-size: .75rem; font-weight: 400; color: var(--ink-3); }

/* Home: the six products as a ruled index. A line each: its picture, what it is called, the one thing
   it is for. The whole line is the link. */
.pidx { display: grid; border-bottom: 1px solid var(--hair-2); }
.pidx > li { border-top: 1px solid var(--hair-2); min-width: 0; }
.pidx__item { display: grid; grid-template-columns: 104px minmax(0, 1fr) auto; align-items: center; gap: 14px; padding-block: 16px; color: inherit; text-decoration: none; transition: transform var(--t-press) ease-out; }
.pidx__item:active { transform: scale(.99); }
.pidx__pic .pshot { border-radius: 10px; }
/* At this size a title card keeps the business's name and nothing else. */
.pidx__pic .pshot__card { padding: 9px 11px; }
.pidx__pic .pshot__card b { font-size: .75rem; line-height: 1.2; letter-spacing: 0; }
.pidx__pic .pshot__card span, .pidx__pic .x-plate__mark, .pidx__pic .pshot--own .pshot__card { display: none; }
.pidx__pic .x-plate::before { inset: 5px; border-radius: 6px; }
.pidx__pic .pshot--own > .glyph { position: static; margin: auto; width: 28px; height: 28px; }
.pidx__pic .pshot--own { display: grid; }
.pidx__body { display: grid; gap: 2px; min-width: 0; }
.pidx__kicker { font-size: .8125rem; font-weight: 500; line-height: 1.4; color: var(--ink-3); }
.pidx__name { font-size: 1.1875rem; line-height: 1.25; font-weight: 600; letter-spacing: var(--trk-head); }
:lang(th) .pidx__name { line-height: 1.45; }
.pidx__out { margin-top: 2px; max-width: 46ch; font-size: .9375rem; line-height: 1.45; color: var(--ink-2); text-wrap: pretty; }
:lang(th) .pidx__out { line-height: 1.65; }
.pidx__item > .i { color: var(--accent); transition: transform var(--t-fast) var(--ease); }
/* Custom work, beside the products: said plainly, with one way on. */
.custom { display: grid; gap: 16px 32px; align-items: center; margin-top: 28px; padding: clamp(20px, 2.6vw, 30px); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); }
.custom__text { display: grid; gap: 8px; min-width: 0; }
.custom__h { font-size: clamp(1.25rem, 1.1rem + .6vw, 1.5rem); line-height: 1.25; font-weight: 600; letter-spacing: var(--trk-head); }
.custom__p { max-width: 68ch; color: var(--ink-2); text-wrap: pretty; }
:lang(th) .custom__h { line-height: 1.45; }
.custom .btn { justify-self: start; }
@media (min-width: 820px) { .custom { grid-template-columns: minmax(0, 1fr) auto; } .custom .btn { justify-self: end; } }
.pidx__note { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 18px; }
@media (min-width: 640px) {
  .pidx__item { grid-template-columns: 168px minmax(0, 1fr) auto; gap: 24px; padding-block: 20px; }
  .pidx__pic .pshot { border-radius: var(--r-m); }
  .pidx__pic .pshot__card { padding: 12px 14px; }
  .pidx__pic .pshot__card b { font-size: .9375rem; }
}
@media (min-width: 1000px) { .pidx { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(40px, 5vw, 72px); } }

/* Home: "Start from what you run". Six kinds of business; each leads to its own page, and offers its
   example where one is built. */
.routes--biz { align-items: stretch; }
.biz { display: flex; flex-direction: column; min-width: 0; border-radius: var(--r-l); background: rgba(255, 255, 255, .035); box-shadow: inset 0 0 0 1px var(--hair-dark); }
.biz .route { flex: 1; height: auto; align-content: start; border-radius: var(--r-l); background: none; box-shadow: none; }
.biz__ex { --xt-hair: var(--hair-dark); --xt-2: var(--on-dark-2); display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0 10px; margin-inline: 22px; padding-block: 4px 8px; border-top: 1px solid var(--hair-dark); font-size: .9375rem; line-height: 1.3; }
:lang(th) .biz__ex { line-height: 1.45; }
.biz__ex .exlink { justify-self: start; display: flex; align-items: center; min-height: 44px; overflow-wrap: anywhere; text-decoration-color: var(--hair-dark); }
@media (min-width: 1000px) { .routes--biz { grid-template-columns: repeat(3, 1fr); } }
/* One column on a phone: six short cards, so the section stays compact. */
@media (max-width: 639px) {
  .biz .route { gap: 4px; padding: 16px 46px 12px 18px; }
  .biz .route .i { right: 18px; top: 20px; }
  .biz .route__h { font-size: 1.125rem; }
  .biz .route__p { font-size: .875rem; }
  .biz__ex { margin-inline: 18px; padding-block: 0 4px; font-size: .875rem; }
}

/* The catalogue opens with a short head, so the products start on the first screen. */
.cat-intro { padding-block: clamp(26px, 3.4vw, 48px) clamp(20px, 2.4vw, 30px); }
.cat-intro__in { display: grid; gap: 14px 48px; align-items: end; }
.cat-intro .h1 { max-width: 18ch; font-size: clamp(2rem, 1.3rem + 2.3vw, 3.125rem); }
:lang(th) .cat-intro .h1 { font-size: clamp(1.875rem, 1.25rem + 2vw, 2.75rem); }
.cat-intro__side { display: grid; gap: 10px; justify-items: start; }
.cat-intro .lead { max-width: 46ch; font-size: clamp(1rem, .95rem + .3vw, 1.1875rem); }
@media (min-width: 900px) { .cat-intro__in { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); } }

/* The catalogue's card: picture, one outcome, a few capabilities, one main action. Compare and Add to
   enquiry share a quieter row at the foot of every card. The card itself is not a link. */
.pcard--full { gap: 0; padding: 8px; }
.pcard__pic { position: relative; }
.pcard__pic .pshot { border-radius: 21px; }
.pcard__pic .pshot--plate .x-plate__mark { display: none; }
.pcard__cap { position: absolute; left: 14px; top: 14px; }
.pcard__cap .exmark { background: var(--surface); }
.pcard--full .pcard__body { flex: 1; display: flex; flex-direction: column; gap: 8px; padding: 18px clamp(10px, 1.4vw, 16px) 18px; }
.pcard__kicker { font-size: .8125rem; font-weight: 500; line-height: 1.4; color: var(--ink-3); }
.pcard--full .pcard__name { margin-top: -4px; }
.pcard--full .pcard__caps { gap: 8px; margin-top: 6px; }
.pcard--full .pcard__actions { justify-content: flex-start; gap: 8px 20px; padding-top: 16px; }
.pcard__more { min-height: 40px; }
.pcard__tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 14px; margin-inline: clamp(10px, 1.4vw, 16px); padding-block: 6px 4px; border-top: 1px solid var(--hair); }
.pcard__tools .pcard__compare { align-self: center; min-height: 44px; }
.pcard__tools .js-add { margin-right: -6px; box-shadow: none; }
/* "What comes next" for a comparison, in each card that is ticked: one more is needed, or "View comparison" and how many. */
.pcard__cmp { flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 0 12px; min-height: 44px; font-size: .875rem; line-height: 1.4; color: var(--ink-2); }
.pcard__cmp .link { min-height: 44px; }
.js-cmp-note:empty { display: none; }
.js-cmp-n { font-variant-numeric: tabular-nums; }

/* The comparison: a table. One row per thing compared, so the same thing sits on the same line for
   every product; the first two rows are the short ones that tell the products apart. */
.cmp { scroll-margin-top: calc(var(--nav-h) + 16px); }
.cmp__head { align-items: center; margin-bottom: 14px; }
.cmp__table { width: 100%; border-collapse: collapse; table-layout: fixed; text-align: left; }
.cmp__table th, .cmp__table td { padding: 16px 24px 16px 0; vertical-align: top; font-weight: 400; }
.cmp__table tr > :last-child { padding-right: 0; }
.cmp__row { border-top: 1px solid var(--hair-2); }
.cmp__row--head { border-top: 0; }
.cmp__table .cmp__dim { width: 11rem; padding-top: 18px; font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.cmp__table .cmp__col { vertical-align: bottom; }
.cmp__name { display: block; font-size: 1.25rem; line-height: 1.2; font-weight: 600; letter-spacing: var(--trk-head); color: var(--ink); }
:lang(th) .cmp__name { line-height: 1.4; }
.cmp__sub { display: block; margin-top: 4px; font-size: .875rem; line-height: 1.4; color: var(--ink-3); }
.cmp__table td { font-size: .9375rem; color: var(--ink-2); }
.cmp__row--key td { font-size: 1rem; font-weight: 500; color: var(--ink); }
.cmp__who { display: none; }
.cmp__steps { counter-reset: cs; display: grid; gap: 4px; }
.cmp__steps li { counter-increment: cs; display: flex; gap: 10px; }
.cmp__steps li::before { content: counter(cs); flex: none; width: 1.1em; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; }
.cmp__list { display: grid; gap: 4px; }
.cmp__list li { position: relative; padding-left: 16px; }
.cmp__list li::before { content: ""; position: absolute; left: 2px; top: .66em; width: 5px; height: 5px; border-radius: 50%; background: var(--ink-4); }
:lang(th) .cmp__list li::before { top: .8em; }
.cmp__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; }
.cmp__acts .link { min-height: 44px; }
.cmp__acts .js-add { margin-left: -6px; }
.cmp__drop { display: inline-flex; align-items: center; min-height: 44px; padding: 0; border: 0; background: none; font-size: .875rem; color: var(--ink-3); text-decoration: underline; text-decoration-color: var(--hair-2); text-underline-offset: 3px; }
/* A narrow screen reads the table one row at a time: the thing compared as a heading, then each
   product's name beside its value. Nothing scrolls sideways. The table keeps its roles (the markup
   names them), so a screen reader still hears a table. */
@media (max-width: 719px) {
  .cmp__table, .cmp__table thead, .cmp__table tbody, .cmp__table tr, .cmp__table th, .cmp__table td { display: block; }
  .cmp__table .cmp__row--head { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 16px; }
  .cmp__table .cmp__row--head .cmp__dim { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); }
  .cmp__table .cmp__col { padding: 8px 12px; border-radius: var(--r-s); box-shadow: inset 0 0 0 1px var(--hair-2); }
  .cmp__name { font-size: .9375rem; letter-spacing: 0; }
  .cmp__sub { display: none; }
  .cmp__row { padding-block: 14px 8px; }
  .cmp__table .cmp__dim { width: auto; padding: 0 0 4px; }
  .cmp__table td { display: grid; grid-template-columns: minmax(0, 6.75rem) minmax(0, 1fr); gap: 0 14px; padding: 9px 0; }
  .cmp__table td + td { border-top: 1px solid var(--hair); }
  .cmp__row--key td { font-size: .9375rem; }
  .cmp__who { display: block; font-size: .8125rem; font-weight: 600; line-height: 1.45; color: var(--ink); }
}

/* A finger: every action on these two pages is at least 44px tall. */
@media (pointer: coarse) {
  .cat-intro .link, .filter .chip, .filter .link, .cmp__head .link, [data-page="home"] .head .link { min-height: 44px; }
  .pcard--full .btn--s, .pcard__more, .cmp__acts .btn--s { min-height: 44px; }
}

@media (hover: hover) and (pointer: fine) {
  .pidx__item:hover > .i { transform: translateX(3px); }
  .pidx__item:hover .pidx__name { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--hair-2); }
  .pcard--full:hover { box-shadow: var(--shadow-card); }
  .biz .route:hover { background: rgba(255, 255, 255, .06); }
  .biz__ex .exlink:hover { text-decoration-color: currentColor; }
  .cmp__drop:hover { color: var(--ink); text-decoration-color: currentColor; }
}
@media (prefers-reduced-motion: reduce) {
  .pidx__item:active, .pidx__item:hover > .i { transform: none; }
}
@media (prefers-contrast: more) { .pshot::after { box-shadow: inset 0 0 0 1px var(--hair-2); } }
/* (home and catalogue: end) */

/* ---- industry pages ---- */
/* /industries/<trade> (src/pages/industry.mjs) and what /industries gained with the examples
   (src/pages/industries.mjs). A trade's page opens with what O2 builds for it beside that trade's first
   example, then follows its own order of sections; the section each trade has to itself is drawn here
   (.ip-contrast, .ip-answers and .ip-facts, .ip-path, .ip-anatomy, .ip-split). The examples themselves are
   the parts in "example components" above; the "On this page" bar is the product pages' (.pnav). Nothing
   drawn here can be pressed unless it is a link, and every colour is a token, so both themes follow. */
[data-page="industry"] { --pnav-h: 48px; }  /* the bar's height; "product pages" above sets the same on main, and that one wins while it is there */
.ip { scroll-margin-top: calc(var(--pnav-h, 0px) - 16px); }  /* a section the bar links to stops just under it */
@media (max-height: 480px) { .ip { scroll-margin-top: 0; } }
/* A product named at the start of an answer is a link in running text: a fine underline says so, not its weight alone. */
.need__a a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--hair-2); text-decoration-color: color-mix(in srgb, currentColor 30%, transparent); }
/* A link that stands by itself on these pages is a comfortable thing to press: 44px tall. */
.ip .link, [data-page="industries"] .intro .chip { min-height: 44px; }
.ip-ai { margin-top: 22px; max-width: 64ch; display: grid; justify-items: start; gap: 2px; }

/* The opening: the words, and beside them (under them on a phone or a tablet) the example to try. */
.ip-hero { padding-block: clamp(24px, 2.6vw, 36px) clamp(32px, 4.4vw, 64px); }
.ip-hero .crumbs { margin-bottom: clamp(10px, 1.2vw, 16px); }
.ip-hero__in { display: grid; gap: clamp(32px, 5vw, 64px); }
.ip-hero__text, .ip-hero__try { min-width: 0; }
.ip-hero__text .h1 { margin-top: 0; }
.ip-hero__try { display: grid; gap: 4px; align-content: start; }
@media (min-width: 1000px) {
  .ip-hero__in--try { grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr); align-items: center; }
  .ip-hero__try .xt__shot { aspect-ratio: 16 / 9; }  /* beside the words the picture is a little shallower, so the way into the example stays on the first screen */
  .ip-hero__in--try .h1 { font-size: clamp(2.25rem, 1.1rem + 2.4vw, 3.25rem); }
  :lang(th) .ip-hero__in--try .h1 { font-size: clamp(2rem, 1.1rem + 2vw, 2.875rem); }
}

/* A line the registry draws for an example (a hotel's restaurant is not room service), and a trade's own limits. */
/* The same mark as .nsel__bound: a dot, not a rule down one side. */
.ip-bound { position: relative; max-width: 68ch; margin-top: 22px; padding-left: 16px; font-size: .9375rem; color: var(--ink-2); text-wrap: pretty; }
.ip-bound::before { content: ""; position: absolute; left: 1px; top: .62em; top: calc(.5lh - 3px); width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.ip-bound + .ip-bound { margin-top: 12px; }

/* Needs, in the trade's own words: three across, each with the product that answers it. */
.ip-needs { display: grid; gap: 0 clamp(24px, 3vw, 44px); }
.ip-needs .need { align-content: start; gap: 10px; padding: 22px 0 14px; }
.ip-needs .need__q { font-size: 1.25rem; line-height: 1.28; text-wrap: balance; }
:lang(th) .ip-needs .need__q { line-height: 1.5; }
@media (min-width: 900px) { .ip-needs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* What to start with: the one product, then what to add and what to leave out. */
.ip-start { display: grid; gap: clamp(28px, 5vw, 80px); }
.ip-start__main { display: grid; gap: 16px; justify-items: start; align-content: start; min-width: 0; }
.ip-start__main .lead { max-width: 46ch; }
.ip-start__product { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px; min-height: 68px; margin-top: 8px; padding: 12px 18px 12px 12px; border-radius: var(--r-l); background: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair-2); text-decoration: none; transition: transform var(--t-press) ease-out, box-shadow var(--t-fast) ease; }
.band:not(.band--tint) .ip-start__product { background: var(--surface); }
.ip-start__product:active { transform: scale(.985); }
.ip-start__icon { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 13px; box-shadow: inset 0 0 0 1px var(--hair-2); }
.ip-start__name { display: grid; gap: 1px; min-width: 0; }
.ip-start__name b { font-weight: 600; letter-spacing: var(--trk-sub); }
.ip-start__name span { font-size: .875rem; line-height: 1.45; color: var(--ink-3); }
.ip-start__product > .i, .ip-start__p .i { color: var(--accent); transition: transform var(--t-fast) var(--ease); }
.ip-start__rest { min-width: 0; }
.ip-start__h { margin-bottom: 6px; font-size: .875rem; line-height: 1.4; font-weight: 550; color: var(--ink-3); }
.ip-start__rest .needs + .ip-start__h { margin-top: 30px; }
.ip-start__rest .needs { border-bottom: 1px solid var(--hair-2); }
.ip-start__p { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; text-decoration: none; }
.ip-start__rest .need { gap: 0; padding-top: 10px; }
.ip-start__skip .ip-start__p { color: var(--ink-2); }
@media (min-width: 900px) { .ip-start { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); } }

/* Client work of this kind, or the plain statement that there is none to show: never beside an example. */
.ip-ev { display: grid; gap: clamp(20px, 4vw, 64px); }
.ip-ev__body { display: grid; gap: 18px; justify-items: start; min-width: 0; }
.ip-ev__body .lead { max-width: 50ch; color: var(--ink); }
.ip-ev__card { display: grid; width: 100%; max-width: 740px; border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); }
.band--tint .ip-ev__card { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.ip-ev__img { margin: 8px 8px 0; border-radius: 21px; overflow: hidden; background: var(--sunken); aspect-ratio: 16 / 10; }
.ip-ev__img img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
:root[data-theme="dark"] .ip-ev__img img { filter: brightness(.9) saturate(.94); }
.ip-ev__text { display: grid; gap: 6px; align-content: center; min-width: 0; padding: 16px 20px 20px; }
.ip-ev__built { margin-top: 4px; font-size: .9375rem; color: var(--ink-2); }
.ip-ev__note { max-width: 62ch; font-size: .9375rem; color: var(--ink-2); text-wrap: pretty; }
@media (min-width: 700px) {
  .ip-ev__card { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
  .ip-ev__img { margin: 8px 0 8px 8px; }
  .ip-ev__text { padding: 20px 24px; }
}
@media (min-width: 900px) { .ip-ev { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); } }

/* Salons and clinics: the same booking, decided differently. Each aspect is answered twice; from 800px the
   two answers sit in columns under one pair of headings, below that each answer carries its own. */
.ip-contrast { border-top: 1px solid var(--hair-2); }
.ip-contrast__cols { display: none; }
.ip-contrast__row { display: grid; gap: 12px; padding: 20px 0; border-bottom: 1px solid var(--hair-2); }
.ip-contrast dt { font-size: 1.0625rem; font-weight: 600; letter-spacing: var(--trk-sub); }
.ip-contrast dd { color: var(--ink-2); text-wrap: pretty; }
.ip-contrast__for { display: block; margin-bottom: 2px; font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
@media (min-width: 800px) {
  .ip-contrast__cols, .ip-contrast__row { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 5fr) minmax(0, 5fr); gap: clamp(20px, 3vw, 48px); }
  .ip-contrast__cols { padding: 14px 0; border-bottom: 1px solid var(--hair-2); font-size: .875rem; font-weight: 550; color: var(--ink-3); }
  .ip-contrast__for { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* Retail: one question, two answers; then what a product page has to answer. */
.ip-decision .h2 { max-width: 20ch; }
.ip-answers { display: grid; margin-top: clamp(24px, 3.4vw, 44px); border-top: 1px solid var(--hair-2); }
.ip-answer { display: grid; gap: 8px; align-content: start; padding: 22px 0 24px; border-bottom: 1px solid var(--hair-2); }
.ip-answer__tag { font-size: 1.25rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); }
:lang(th) .ip-answer__tag { line-height: 1.5; }
.ip-answer p { max-width: 54ch; color: var(--ink-2); text-wrap: pretty; }
@media (min-width: 800px) { .ip-answers { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 clamp(28px, 5vw, 80px); } }
.ip-facts { display: grid; gap: 0 clamp(18px, 2.2vw, 30px); }
@media (min-width: 480px) { .ip-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 760px) { .ip-facts { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .ip-facts { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.ip-facts > div { display: grid; gap: 6px; align-content: start; padding: 18px 0 20px; border-top: 1px solid var(--hair-2); }
.ip-facts dt { font-weight: 600; letter-spacing: var(--trk-sub); }
.ip-facts dd { font-size: .9375rem; color: var(--ink-2); }

/* Hotels: the way an enquiry travels, in three steps, and what is not part of it. */
.ip-path { display: grid; gap: 10px; counter-reset: ip; }
.ip-path li { position: relative; display: grid; gap: 6px; align-content: start; padding: 20px 20px 22px 62px; border-radius: var(--r-l); background: var(--surface); box-shadow: var(--shadow-card); counter-increment: ip; }
.band--tint .ip-path li { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.ip-path li::before { content: counter(ip, decimal-leading-zero); position: absolute; left: 20px; top: 22px; font-size: .8125rem; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.ip-path h3 { font-size: 1.0625rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); }
:lang(th) .ip-path h3 { line-height: 1.5; }
.ip-path p { font-size: .9375rem; color: var(--ink-2); }
.ip-not { display: grid; gap: 14px; max-width: 780px; margin-top: clamp(28px, 3.6vw, 48px); }
.ip-not ul { display: grid; gap: 10px; }
.ip-not li { position: relative; padding-left: 28px; color: var(--ink-2); }
.ip-not li::before, .ip-not li::after { content: ""; position: absolute; left: 3px; top: .78em; width: 13px; height: 1.75px; border-radius: 1px; background: var(--ink-3); transform: rotate(45deg); }
.ip-not li::after { transform: rotate(-45deg); }
@media (min-width: 900px) {
  .ip-path { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ip-path li { padding: 54px 22px 24px; }
}

/* Construction: what a project page shows, beside what the enquiry asks. */
.ip-anatomy { display: grid; gap: clamp(28px, 5vw, 80px); }
.ip-anatomy .h3 { margin-bottom: 16px; }
.ip-asks { border-top: 1px solid var(--hair-2); }
.ip-asks > div { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 5fr); gap: 4px 20px; padding: 14px 0; border-bottom: 1px solid var(--hair-2); }
.ip-asks dt { font-weight: 600; letter-spacing: var(--trk-sub); }
.ip-asks dd { color: var(--ink-2); }
@media (max-width: 419px) { .ip-asks > div { grid-template-columns: minmax(0, 1fr); } }
@media (min-width: 900px) { .ip-anatomy { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Golf: what is booked on the spot, beside what is sent as a request. The tag says which in words. */
.ip-split { display: grid; gap: 14px; }
.ip-split__side { display: grid; gap: 12px; align-content: start; padding: clamp(20px, 2.6vw, 32px); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-card); }
.band--tint .ip-split__side { background: var(--canvas); box-shadow: 0 0 0 1px var(--hair); }
.ip-split__tag { justify-self: start; padding: 4px 10px; border-radius: var(--pill); background: var(--ok-soft); font-size: .8125rem; line-height: 1.3; font-weight: 550; color: var(--ok); }
:lang(th) .ip-split__tag { line-height: 1.5; }
.ip-split__side--ask .ip-split__tag { background: var(--warn-soft); color: var(--warn); }
.ip-split__side ul { display: grid; gap: 10px; margin-top: 4px; }
.ip-split__side li { position: relative; padding-left: 20px; color: var(--ink-2); }
.ip-split__side li::before { content: ""; position: absolute; left: 3px; top: .68em; width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); }
@media (min-width: 800px) { .ip-split { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* /industries: a section's example, above its answers, and the closing section for everyone else. */
.ind__try { margin-bottom: clamp(24px, 3vw, 36px); }
.ind__try .xt--large .xt__label { font-size: 1.3125rem; line-height: 1.22; }
:lang(th) .ind__try .xt--large .xt__label { line-height: 1.4; }
.ind__try .xt--large .xt__actions { margin-top: 8px; }
.ind__find { min-height: 44px; padding-inline: 6px; }
/* The way on to a business's own page names it, and some names are long: on a narrow phone the button takes two lines. */
.ind__head .actions .btn { max-width: 100%; padding-block: 10px; border-radius: 26px; white-space: normal; text-wrap: balance; }
@container xt (min-width: 540px) {  /* in a section the picture goes beside the words a little sooner than elsewhere */
  .ind__try .xt--large .xt__in { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: center; gap: clamp(22px, 5cqi, 40px); }
}
.ind__other { display: grid; gap: clamp(20px, 4vw, 64px); align-items: end; }
.ind__other > div { display: grid; gap: 18px; justify-items: start; }
.ind__other .lead { max-width: 44ch; }
.ind__other .note { margin-top: 0; }
@media (min-width: 900px) { .ind__other { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); } }

@media (hover: hover) and (pointer: fine) {
  .need__a a:hover { text-decoration-color: currentColor; }
  .ip-start__product:hover { box-shadow: inset 0 0 0 1px var(--ink-3); }
  .ip-start__product:hover > .i, .ip-start__p:hover .i { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) { .ip-start__product:active, .ip-start__product:hover > .i, .ip-start__p:hover .i { transform: none; } }
@media (prefers-contrast: more) { .ip-ev__card, .ip-path li, .ip-split__side { box-shadow: 0 0 0 1px var(--hair-2); } }

/* ---- the audit pass of 11 October 2026 ------------------------------------ */
/* The opening: the example's own action sits under its card, apart from the page's two main actions. */
.hero__try { display: flex; margin-top: 14px; padding-inline: 10px; }
/* Each supporting project in the proof strip can be opened. */
.proof__meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 16px; }
.proof__go { font-size: .875rem; }
/* A row that runs off the side of a narrow screen fades at the side that has more (src/js/site.js marks it). */
[data-more="end"] { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent); }
[data-more="start"] { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 48px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 48px), transparent); }
[data-more="both"] { -webkit-mask-image: linear-gradient(to right, transparent, #000 48px, #000 calc(100% - 48px), transparent); mask-image: linear-gradient(to right, transparent, #000 48px, #000 calc(100% - 48px), transparent); }

/* Under the four stages on the home page: what a quote depends on, and how payment works. */
.expect { display: grid; gap: 12px 48px; margin-top: clamp(32px, 4vw, 56px); padding-top: clamp(24px, 3vw, 36px); border-top: 1px solid var(--hair-2); }
.expect__col { display: grid; gap: 12px; align-content: start; }
.expect__h { font-size: 1.0625rem; line-height: 1.35; font-weight: 600; letter-spacing: var(--trk-sub); }
.expect__col p { max-width: 68ch; color: var(--ink-2); text-wrap: pretty; }
@media (min-width: 900px) { .expect { grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); } }

/* "Investment, timing and ongoing costs": the full explanation on the process page. */
.costs__lead { max-width: 62ch; }
.costs { display: grid; gap: clamp(28px, 4vw, 64px); margin-top: clamp(28px, 3.6vw, 48px); }
.costs__h { margin-bottom: 14px; font-size: 1.0625rem; line-height: 1.35; font-weight: 600; letter-spacing: var(--trk-sub); }
.costs__quote .ticks { color: var(--ink-2); }
.costs__rows { display: grid; border-bottom: 1px solid var(--hair-2); }
.costs__rows > div { display: grid; gap: 6px; padding: 20px 0; border-top: 1px solid var(--hair-2); }
.costs__rows dt { font-weight: 600; letter-spacing: var(--trk-sub); }
.costs__rows dd { max-width: 64ch; color: var(--ink-2); text-wrap: pretty; }
@media (min-width: 760px) { .costs__rows > div { grid-template-columns: minmax(0, 3fr) minmax(0, 8fr); gap: 24px; } }
@media (min-width: 1000px) { .costs { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); align-items: start; } .costs__quote { position: sticky; top: calc(var(--nav-h) + 24px); } }
#costs { scroll-margin-top: calc(var(--nav-h) + var(--pnav-h, 0px) + 12px); }

/* The short version, on a product page. */
.costs-s { display: grid; gap: 12px; margin-top: clamp(28px, 3.6vw, 44px); padding: 22px 24px; border-radius: var(--r-l); background: var(--canvas); box-shadow: inset 0 0 0 1px var(--hair); }
.costs-s__h { font-size: 1.0625rem; line-height: 1.35; font-weight: 600; letter-spacing: var(--trk-sub); }
.costs-s__list { display: grid; gap: 8px; max-width: 78ch; color: var(--ink-2); }
.costs-s__list li { position: relative; padding-left: 18px; text-wrap: pretty; }
.costs-s__list li::before { content: ""; position: absolute; left: 3px; top: .62em; width: 5px; height: 5px; border-radius: 50%; background: var(--ink-4); }
.pd-near { gap: 14px; }

/* Email and the phone numbers on one line, under a page's opening words. */
.directline { display: flex; flex-wrap: wrap; align-items: center; gap: 0 20px; margin-top: 18px; font-size: .9375rem; color: var(--ink-3); }
.directline a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 550; color: var(--ink); text-decoration: none; overflow-wrap: anywhere; }
.directline a:hover { text-decoration: underline; text-underline-offset: 3px; }
/* A phone number with the person who answers it (src/lib/html.mjs telLink): the name lighter than the number, and the
   name and the number each kept whole; where the line is short the number goes under the name. */
a:has(> .tel__who) { display: inline-flex; flex-wrap: wrap; align-items: center; column-gap: .35em; }
.tel__who { font-weight: 400; white-space: nowrap; }
.tel__num { white-space: nowrap; }
/* On a phone the footer's contact column runs the width of the page, so the address and the numbers are not squeezed
   into half of it. */
@media (max-width: 899px) { .foot__contact { grid-column: 1 / -1; } }

/* The contact page: what happens after sending, beside the form. */
.next { display: grid; counter-reset: nx; }
.next li { counter-increment: nx; position: relative; padding: 14px 0 14px 34px; border-top: 1px solid var(--hair); color: var(--ink-2); text-wrap: pretty; }
.next li::before { content: counter(nx, decimal-leading-zero); position: absolute; left: 0; top: 17px; font-size: .8125rem; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.more summary .field__hint { font-weight: 400; }
/* The contact form's fold: its name and what it holds on two lines where they do not fit on one, the sign beside the
   name (the audit of 17 October 2026 found the three squeezed into columns on a phone). */
.more summary.more__sum { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; column-gap: 10px; row-gap: 0; padding-block: 8px; }
.more__sum::before { grid-row: 1; }
.more__sum .more__l, .more__sum .field__hint { grid-column: 2; }
@media (min-width: 560px) { .more summary.more__sum { grid-template-columns: auto auto minmax(0, 1fr); } .more__sum .field__hint { grid-column: 3; } }
.more[open] > summary { margin-bottom: 6px; }

/* A case study: the client over the headline, then the customer's steps, each with a real screen. */
.cs__client { margin-top: 6px; font-weight: 600; }
.cs__client span { margin-left: 8px; font-weight: 400; color: var(--ink-3); }
.cs__head .cs__h1 { margin-top: 2px; max-width: 22ch; font-size: clamp(2rem, 1.3rem + 2.4vw, 3.25rem); }
.cs__sub { margin-top: 28px; margin-bottom: 14px; }
.cs__plain { max-width: 52ch; color: var(--ink-2); text-wrap: pretty; }
.cs-steps { display: grid; gap: clamp(40px, 6vw, 88px); counter-reset: cs; }
.cs-step { counter-increment: cs; display: grid; gap: 20px 48px; align-items: start; padding-top: clamp(22px, 3vw, 32px); border-top: 1px solid var(--hair-2); }
.cs-step__text { display: grid; gap: 10px; align-content: start; }
.cs-step__text::before { content: counter(cs, decimal-leading-zero); font-size: .8125rem; font-weight: 550; color: var(--accent-press); font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.cs-step__text p { max-width: 46ch; color: var(--ink-2); text-wrap: pretty; }
.cs-step__shots { display: grid; gap: 16px; align-items: end; min-width: 0; }
.cs-step__shots figure { display: grid; gap: 12px; min-width: 0; }
.cs-step__shots img { width: 100%; height: auto; border-radius: var(--r-l); box-shadow: var(--shadow-lift); }
.cs-step__shots figcaption { font-size: .875rem; color: var(--ink-3); }
.cs-step__shots figure.is-portrait img { width: min(100%, 17.5rem); }
@media (min-width: 900px) {
  .cs-step { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
  .cs-step__text { position: sticky; top: calc(var(--nav-h) + 24px); }
  .cs-step__shots--pair { grid-template-columns: minmax(0, 2.6fr) minmax(0, 1fr); gap: 24px; }
}

/* The About page: the approach in one commissioned project, then the working relationship. */
.seen { display: grid; gap: clamp(24px, 4vw, 64px); align-items: start; }
.seen__text { display: grid; gap: 14px; align-content: start; justify-items: start; }
.seen__pair { display: grid; width: 100%; }
.seen__pair > div { display: grid; gap: 6px; padding: 18px 0; border-top: 1px solid var(--hair-2); }
.seen__pair dt { font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.seen__pair dd { max-width: 52ch; color: var(--ink-2); text-wrap: pretty; }
.seen__img { display: grid; gap: 12px; }
.seen__img img { width: 100%; height: auto; border-radius: var(--r-l); box-shadow: var(--shadow-lift); }
.seen__img figcaption { font-size: .875rem; color: var(--ink-3); }
@media (min-width: 900px) { .seen { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); } }
.rel { display: grid; gap: 0 48px; margin-top: 32px; }
.rel > div { display: grid; gap: 8px; align-content: start; padding: 22px 0; border-top: 1px solid var(--hair-2); }
.rel dt { font-weight: 600; letter-spacing: var(--trk-sub); }
.rel dd { max-width: 52ch; color: var(--ink-2); text-wrap: pretty; }
@media (min-width: 760px) { .rel { grid-template-columns: repeat(2, minmax(0, 1fr)); } }


/* The co-founders by name (the owner gave the two names and titles on 12 October 2026). About: the title and what was
   studied on one line under the name. Home: the two names side by side, each over its title. */
.profile .profile__role { display: flex; flex-wrap: wrap; gap: 2px 12px; align-items: baseline; font-size: .9375rem; max-width: none; }
.profile .profile__role b { font-weight: 600; color: var(--ink); letter-spacing: var(--trk-sub); }
.founders__who { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px 40px; }
.founders__who li { display: grid; gap: 2px; padding-top: 14px; border-top: 1px solid var(--hair-2); }
.founders__who b { font-weight: 600; letter-spacing: var(--trk-sub); }
.founders__who span { color: var(--ink-2); font-size: .9375rem; }
@media (min-width: 520px) { .founders__who { grid-template-columns: repeat(2, minmax(0, max-content)); } }

/* Who is who in the photograph, in a line under it on About (the owner said which on 12 October 2026). The picture
   keeps its rounded corners; its frame no longer clips, so the line can sit beneath it. */
.about__img { background: none; overflow: visible; border-radius: 0; }
.about__img img { display: block; border-radius: var(--r-xl); background: var(--sunken); }
.about__img figcaption { margin-top: 10px; font-size: .875rem; color: var(--ink-3); }

/* Custom work and services (12 October 2026). The section's page lists each piece of work as a row that is one
   link; a service page sets what the work covers in two columns and puts what it is not beside the cost note.
   The header's Products menu, the phone menu and the footer each name the section under the six products. */
.svc-list { display: grid; gap: 14px; }
.svc { display: grid; gap: 6px; align-content: start; padding: clamp(20px, 2.6vw, 28px); border-radius: var(--r-l); background: var(--surface); box-shadow: 0 0 0 1px var(--hair); color: inherit; text-decoration: none; transition: box-shadow .18s ease, transform .1s ease-out; }
.band--tint .svc { background: var(--canvas); }
.svc:hover { box-shadow: var(--shadow-card); }
.svc:active { transform: scale(.985); }
.svc__h { display: flex; align-items: center; justify-content: space-between; gap: 16px; font-size: 1.1875rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); }
.svc__h .i { flex: none; color: var(--accent); }
.svc__p { color: var(--ink-2); font-size: .9375rem; max-width: 52ch; }
.svc-also { margin-top: 24px; max-width: 70ch; color: var(--ink-2); }
.svc-also b { color: var(--ink); font-weight: 600; }
.svc-lead { max-width: 60ch; margin-bottom: 8px; }
.svc-covers { display: grid; gap: 0 clamp(28px, 4vw, 64px); }
.svc-covers > div { padding: 20px 0; border-top: 1px solid var(--hair-2); }
.svc-covers dt { font-size: 1.0625rem; font-weight: 600; letter-spacing: var(--trk-sub); }
.svc-covers dd { margin-top: 4px; color: var(--ink-2); max-width: 52ch; text-wrap: pretty; }
.svc-more { display: flex; width: fit-content; margin-top: 8px; }
.svc-cols { display: grid; gap: clamp(28px, 4vw, 64px); align-items: start; }
.svc-not { display: grid; gap: 16px; margin-top: 22px; }
.svc-not li { padding-left: 18px; border-left: 2px solid var(--hair-2); color: var(--ink-2); max-width: 62ch; text-wrap: pretty; }
.svc-costs { display: grid; gap: 12px; justify-items: start; }
.svc-costs p { color: var(--ink-2); }
.custom__links { display: flex; flex-wrap: wrap; gap: 6px 22px; margin-top: 14px; }
.pd-beyond { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px; margin-top: 22px; color: var(--ink-2); }
.npanel__more { margin: 6px 4px 0; padding: 10px 8px 0; border-top: 1px solid var(--hair); }
.npanel__more-h { display: inline-block; font-size: .8125rem; font-weight: 550; color: var(--ink-3); text-decoration: none; }
.npanel__more-h:hover, .npanel__more-h[aria-current] { color: var(--accent); }
.npanel__more-list { display: flex; flex-wrap: wrap; gap: 2px 4px; margin: 2px 4px 0; padding: 0 8px 4px; }
.npanel__more-list li a { display: inline-flex; align-items: center; min-height: 36px; padding: 4px 10px; margin-left: -10px; border-radius: var(--r-s); font-size: .9375rem; font-weight: 550; color: var(--ink); text-decoration: none; }
.npanel__more-list li a:focus-visible, .npanel__more-list li a:active { background: var(--canvas); }
.npanel__more-list li a[aria-current] { color: var(--accent); }
.sheet__sub a.sheet__more { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--hair); font-size: .9375rem; color: var(--ink-3); }
.foot__h--sub { margin-top: 22px; }
.foot__h--sub a { color: inherit; text-decoration: none; }
@media (min-width: 760px) { .svc-list--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 760px) { .svc-list--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } .svc-covers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .svc-cols { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); } }
/* Buying guides share the site's type, colour and motion settings. Long text stays narrow. */
.guide-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 2.5rem; }
.guide-card { padding: 2rem 0; border-top: 1px solid var(--hair-2); display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
/* The guides by topic (the audit of 17 October 2026): a heading over each group, its guides as before. */
.guide-group { display: grid; gap: 4px; margin-top: clamp(32px, 4.4vw, 56px); }
.guide-group__h { display: flex; align-items: center; gap: 10px; font-size: 1.25rem; font-weight: 600; letter-spacing: var(--trk-sub); color: var(--ink); }
.guide-group__h::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
.guide-card > p { color: var(--ink-2); line-height: 1.65; }
.guide-card .guide-card__go { margin-top: auto; padding-top: .25rem; }
.guide-card__go a, .guide-reading__links a { min-height: 44px; }
.guide-article { max-width: 52rem; padding-top: 0; padding-bottom: var(--band); }
.guide-meta { color: var(--ink-2); line-height: 1.7; margin-bottom: 2.5rem; }
.guide-meta a, .guide-contents a, .guide-sources a { color: var(--accent); text-decoration: underline; text-underline-offset: .2em; }
.guide-contents { border-top: 1px solid var(--hair-2); border-bottom: 1px solid var(--hair-2); padding: 1.5rem 0; }
.guide-contents h2 { margin-bottom: .75rem; }
.guide-contents p { margin: 0; }
.guide-contents a { display: inline-flex; align-items: center; min-height: 44px; padding: .4rem 0; }
.guide-section { margin-top: 3rem; scroll-margin-top: calc(var(--nav-h) + 2rem); }
.guide-section > h2 { max-width: 100%; margin-bottom: 1.25rem; font-size: clamp(1.5rem, 3.2vw, 2rem); line-height: 1.3; }
.guide-section > p, .guide-section > ul { color: var(--ink-2); font-size: 1.0625rem; line-height: 1.8; margin-top: 1rem; }
.guide-section > ul { padding-left: 1.4rem; }
.guide-section li + li { margin-top: .65rem; }
.guide-sources a { display: inline-block; min-height: 44px; padding-block: .5rem; overflow-wrap: anywhere; }
.guide-reading__links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 2.5rem; }
.guide-reading__links p { padding-top: 1rem; border-top: 1px solid var(--hair-2); }
.guide-reading__links a { line-height: 1.5; align-items: flex-start; }
.guide-reading__links .i { flex-shrink: 0; margin-top: .25rem; }
@media (max-width: 700px) {
  .guide-grid, .guide-reading__links { grid-template-columns: minmax(0, 1fr); }
  .guide-card { padding: 1.5rem 0; }
  .guide-section { margin-top: 2.5rem; }
}

/* Buying decisions: retain the existing palette and type, reduce repeated detail. */
.outcomes { display: grid; gap: 16px; }
.outcome { display: flex; flex-direction: column; gap: 14px; padding: clamp(20px, 2.8vw, 32px); border: 1px solid var(--hair); border-radius: var(--r-l); min-width: 0; }
.outcome > p { color: var(--ink-2); text-wrap: pretty; }
.outcome ul { display: grid; gap: 4px; margin-top: auto; padding-top: 10px; }
.outcome .link { min-height: 44px; }
.home-details { border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair); }
.home-details > summary { cursor: pointer; padding: 22px 4px; font-size: 1.125rem; font-weight: 550; line-height: 1.5; }
.home-details > summary::marker { color: var(--ink-3); }
.home-details > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
.home-details__body { padding: 4px 0 28px; }
.home-details__body > .flow { margin-top: 28px; }
.home-reading { margin-top: 20px; }
.commercial { display: grid; gap: 0 28px; }
/* The same lines, each opened by its heading (a product page): drawn like the questions further down. */
.commercial--fold { gap: 0 28px; align-items: start; }
.commercial--fold details { border-top: 1px solid var(--hair); }
.commercial--fold summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 52px; padding: 10px 0; font-weight: 550; cursor: pointer; list-style: none; }
.commercial--fold summary::-webkit-details-marker { display: none; }
.commercial--fold summary::after { content: ""; flex: none; width: 8px; height: 8px; margin-right: 4px; border-right: 1.75px solid var(--ink-3); border-bottom: 1.75px solid var(--ink-3); transform: rotate(45deg) translate(-2px, -2px); transition: transform var(--t-fast) var(--ease); }
.commercial--fold details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.commercial--fold summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.commercial--fold details p { padding: 0 28px 16px 0; color: var(--ink-2); text-wrap: pretty; }
@media (prefers-reduced-motion: reduce) { .commercial--fold summary::after { transition: none; } }
.commercial > div { padding: 16px 0; border-top: 1px solid var(--hair); }
.commercial dt { margin-bottom: 5px; font-weight: 550; }
.commercial dd { color: var(--ink-2); text-wrap: pretty; }
.costs-s__links { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.costs-s__links .link { min-height: 44px; }
.costs > .costs-s, .costs-s + .costs { margin-top: 32px; }
.product-proof { display: grid; gap: clamp(24px, 4vw, 56px); align-items: center; }
.product-proof__image { aspect-ratio: 16 / 10; overflow: hidden; border-radius: var(--r-l); background: var(--sunken); }
.product-proof__image img { width: 100%; height: 100%; object-fit: cover; object-position: left top; }
.product-proof__copy { display: grid; gap: 12px; justify-items: start; }
.product-proof__copy > p:not(.eyebrow):not(.tags) { color: var(--ink-2); }
.product-proof__copy > .small { color: var(--ink-3); }
@media (min-width: 720px) { .outcomes { grid-template-columns: repeat(3, minmax(0, 1fr)); } .commercial { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .product-proof { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); } }
@media (max-width: 419px) { .costs-s { padding: 20px 16px; } }

/* ---- Decision guides: two approaches side by side (Phase 5; src/pages/compare.mjs) ----------------------------------
   Same grammar as the products comparison above: the dimension as a quiet label, each approach in its own column,
   rows divided by a hairline. On a narrow screen a row is read on its own: the dimension as a heading, then each
   approach with its name above its value. The table keeps its roles, so a screen reader still hears a table. */
.dg { scroll-margin-top: calc(var(--nav-h) + 16px); }
.dg + .dg { padding-top: 0; }
.dg-table { width: 100%; border-collapse: collapse; table-layout: fixed; text-align: left; margin-top: 4px; }
.dg-table th, .dg-table td { padding: 14px 24px 14px 0; vertical-align: top; font-weight: 400; }
.dg-table tr > :last-child { padding-right: 0; }
.dg-table thead th { padding-top: 0; font-size: 1.0625rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); color: var(--ink); vertical-align: bottom; }
.dg-table thead th:first-child { width: 11rem; font-size: .8125rem; font-weight: 550; color: var(--ink-3); }
.dg-table tbody tr { border-top: 1px solid var(--hair-2); }
.dg-table tbody th { width: 11rem; padding-top: 16px; font-size: .8125rem; font-weight: 550; line-height: 1.4; color: var(--ink-3); }
.dg-table td { font-size: .9375rem; line-height: 1.55; color: var(--ink-2); }
.dg-notes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 32px; margin: 28px 0 0; padding-top: 22px; border-top: 1px solid var(--hair-2); }
.dg-notes dt { font-size: .8125rem; font-weight: 600; color: var(--ink); }
.dg-notes dd { margin: 6px 0 0; font-size: .9375rem; line-height: 1.55; color: var(--ink-2); text-wrap: pretty; }
.dg-related { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px; margin-top: 18px; }
.dg-related__h { font-size: .8125rem; color: var(--ink-3); }
.dg-related .link { min-height: 44px; }
.dg-jump__list { display: grid; gap: 2px; margin: 10px 0 0; padding-left: 1.4em; }
.dg-jump__list a { display: inline-flex; align-items: center; min-height: 40px; }
.dg-note { margin-top: 12px; color: var(--ink-3); }
.guide-card--compare { grid-column: 1 / -1; }
@media (max-width: 899px) { .dg-notes { grid-template-columns: 1fr; } }
@media (max-width: 719px) {
  .dg-table, .dg-table thead, .dg-table tbody, .dg-table tr, .dg-table th, .dg-table td { display: block; }
  .dg-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .dg-table tbody tr { padding-block: 14px 6px; }
  .dg-table tbody th { width: auto; padding: 0 0 6px; }
  .dg-table td { padding: 6px 0 8px; }
  .dg-table td::before { content: attr(data-label); display: block; margin-bottom: 2px; font-size: .8125rem; font-weight: 600; color: var(--ink); }
}

/* ---- the home page's opening box (17 October 2026; src/pages/home.mjs starterForm, src/js/starter.js) ----------------
   One column, centred: the promise, the owner's line, a box to write in that is the heaviest surface on the page, ideas
   under it, and what they already use. The examples follow in their own band. */
.hero--start { padding-block: clamp(36px, 6vw, 88px) clamp(20px, 3vw, 40px); }
.starter-wrap { position: relative; z-index: 1; display: grid; justify-items: center; text-align: center; }
.starter__h { margin-top: 18px; max-width: 18ch; }
.starter__lead { margin-top: 18px; max-width: 40ch; }
.starter { width: min(760px, 100%); min-width: 0; margin-top: clamp(24px, 3.4vw, 40px); display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; text-align: start; }
.starter > * { min-width: 0; }
.starter__box { display: grid; border-radius: 24px; background: var(--surface); box-shadow: var(--shadow-lift); transition: box-shadow 200ms var(--ease); }
.starter__box:focus-within { box-shadow: 0 0 0 2px var(--accent), var(--shadow-lift); }
/* Its height follows what is written (src/js/starter.js), its width never does: sized to its content, a long example
   widened the page on a phone (390 px laid out at 510, 17 October 2026). */
.starter__box textarea { display: block; width: 100%; min-width: 0; min-height: 6.5em; max-height: 16em; padding: 20px 22px 8px; border: 0; border-radius: 24px 24px 0 0; resize: none; overflow-y: auto; background: transparent; color: var(--ink); font: inherit; font-size: 1.0625rem; line-height: 1.5; }
.starter__box textarea:focus, .starter__box textarea:focus-visible { outline: none; }
.starter__box textarea::placeholder { color: var(--ink-3); opacity: 1; }
.starter__bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 10px 10px 22px; }
.starter__count { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.starter__go { flex: none; }
/* The adviser's star on the opening's button, lit as it is in the header's link (the owner, 21 October 2026). */
@media (hover: hover) and (pointer: fine) { .starter__go:hover .spark::after { opacity: 1; animation: spark-flow 1.8s linear infinite; } }
.starter__go:focus-visible .spark::after { opacity: 1; animation: spark-flow 1.8s linear infinite; }
@media (prefers-reduced-motion: reduce) { .starter__go .spark::after { animation: none; } }
.starter__err { margin: 0; color: var(--err); }
.starter__ideas { display: grid; gap: 10px; justify-items: center; }
.starter__tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; padding: 4px; border-radius: 999px; background: rgba(var(--ink-rgb), .05); max-width: 100%; }
.starter__tab { min-height: 36px; padding: 0 14px; border: 0; border-radius: 999px; background: transparent; color: var(--ink-2); font: inherit; font-size: .9375rem; font-weight: 550; cursor: pointer; transition: background 180ms var(--ease), color 180ms var(--ease); }
.starter__tab:hover { color: var(--ink); }
.starter__tab[aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px var(--hair), 0 1px 3px rgba(var(--ink-rgb), .08); }
.starter__panel { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 8px; }
.starter__panel[hidden] { display: none; }
.starter__try { color: var(--ink-3); margin-inline-end: 2px; }
.starter__idea, .starter__tool { min-height: 38px; padding: 0 14px; border: 0; border-radius: 999px; background: var(--surface); color: var(--ink); font: inherit; font-size: .9375rem; box-shadow: inset 0 0 0 1px var(--hair-2); cursor: pointer; transition: box-shadow 160ms var(--ease), background 160ms var(--ease), transform 100ms ease-out; }
.starter__idea:hover, .starter__tool:hover { box-shadow: inset 0 0 0 1px var(--ink-3); }
.starter__idea:active, .starter__tool:active { transform: scale(.97); }
.starter__link { font-size: .9375rem; }
.starter__have { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin: 4px 0 0; padding: 0; border: 0; }
.starter__legend { width: 100%; margin-bottom: 8px; padding: 0; text-align: center; font-size: .9375rem; color: var(--ink-2); }
/* A tool they use, chosen: said by a tick and the word in bold, not by colour alone. */
.starter__tool[aria-pressed="true"] { background: rgba(var(--ink-rgb), .06); box-shadow: inset 0 0 0 1.5px var(--ink); font-weight: 600; }
.starter__tool[aria-pressed="true"]::before { content: "✓"; margin-inline-end: 6px; }
.starter__note { margin: 4px 0 0; text-align: center; color: var(--ink-3); }
.starter__note a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--hair-2); }
.starter__note a:hover { text-decoration-color: currentColor; }
/* The ideas and the tools come in once the box is used (src/js/starter.js): the surface arrives, it is not just shown. */
.starter__more { display: grid; gap: 14px; }
.starter__more[hidden] { display: none; }
.starter--open .starter__more { animation: starter-in 280ms var(--ease) both; }
@keyframes starter-in { from { opacity: 0; transform: translateY(-6px); } }
/* The opening's one other way in, and the line that says what kind of studio this is. */
.starter__next { display: grid; justify-items: center; gap: 12px; margin-top: clamp(20px, 2.6vw, 28px); }
.starter__trust { color: var(--ink-3); }
/* The examples' band holds the ring that used to sit in the opening, which clipped it: so does this band, or the ring
   widens the page on a phone (17 October 2026). */
.hero-examples { position: relative; overflow: clip; }
.hero-examples .hero__copy .lead { max-width: 34ch; }
@media (max-width: 560px) {
  .starter__box textarea { padding: 16px 16px 6px; }
  .starter__bar { padding: 6px 8px 8px 16px; }
  .starter__tabs { border-radius: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .starter__box, .starter__tab, .starter__idea, .starter__tool { transition: none; }
  .starter--open .starter__more { animation: none; }
}

/* ---- one place to choose from (the audit of 17 October 2026; src/pages/home.mjs, src/js/home.js) --------------------
   By result, by kind of business, by product. Without the script the three panels follow one another under their own
   headings; with it they are tabs, drawn like the opening's, and only the chosen panel is on show. */
.choose__tabs { display: flex; flex-wrap: wrap; gap: 4px; width: fit-content; max-width: 100%; margin-bottom: clamp(22px, 3vw, 34px); padding: 4px; border-radius: 999px; background: rgba(var(--ink-rgb), .05); }
.choose__tabs[hidden] { display: none; }
.choose__tab { min-height: 40px; padding: 0 16px; border: 0; border-radius: 999px; background: transparent; color: var(--ink-2); font: inherit; font-size: .9375rem; font-weight: 550; cursor: pointer; transition: background 180ms var(--ease), color 180ms var(--ease), transform 100ms ease-out; touch-action: manipulation; }
.choose__tab:hover { color: var(--ink); }
.choose__tab:active { transform: scale(.97); }
.choose__tab[aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px var(--hair), 0 1px 3px rgba(var(--ink-rgb), .08); }
.choose__tab[aria-selected="true"]::before { content: ""; display: inline-block; width: 6px; height: 6px; margin-inline-end: 8px; border-radius: 50%; background: var(--accent); vertical-align: .12em; }
.choose__panel { display: grid; gap: 16px; }
.choose__panel + .choose__panel { margin-top: clamp(36px, 5vw, 56px); }
.choose__panel[hidden] { display: none; }
.choose__panel:focus { outline: none; }
.choose__ph { font-size: 1.25rem; line-height: 1.3; font-weight: 600; letter-spacing: var(--trk-sub); }
.choose__side { max-width: 60ch; margin-top: -8px; color: var(--ink-2); }
.choose--tabs .choose__panel + .choose__panel { margin-top: 0; }
.choose--tabs .choose__ph { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.choose--tabs .choose__side { margin-top: 0; }
.choose .outcome, .choose .pidx__item { background: var(--canvas); }
.choose .ask.ask--light { background: var(--surface); }
@media (max-width: 560px) {
  .choose__tabs { border-radius: 18px; }
  .choose__tab { flex: 1 1 auto; padding: 0 12px; }
}
@media (prefers-reduced-motion: reduce) { .choose__tab { transition: none; } }
/* The home page on a phone, closer together (the audit of 17 October 2026 asked for about 30% less length with nothing
   taken away): each result's links side by side, the four stages with their number beside the heading, and the
   founders' photograph wider than it is tall, cropped around them. */
@media (max-width: 639px) {
  .choose .outcome { gap: 10px; padding: 18px 18px 14px; }
  .choose .outcome ul { display: flex; flex-wrap: wrap; gap: 0 20px; padding-top: 2px; }
  /* The four stages read in order, so on a phone they sit side by side and are swiped through, the next one showing
     at the edge; the page itself never scrolls sideways. */
  [data-page="home"] .steps { display: flex; gap: 12px; margin-inline: calc(var(--gutter) * -1); padding: 2px var(--gutter) 6px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); overscroll-behavior-x: contain; scrollbar-width: none; }
  [data-page="home"] .steps::-webkit-scrollbar { display: none; }
  [data-page="home"] .steps li { flex: 0 0 min(78%, 300px); scroll-snap-align: start; padding: 16px 18px 18px; border: 0; border-radius: var(--r-l); background: var(--surface); box-shadow: inset 0 0 0 1px var(--hair); }
  [data-page="home"] .steps:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--r-l); }
  [data-page="home"] .steps__n { margin-bottom: 4px; }
  [data-page="home"] .band { padding-block: 44px; }
  [data-page="home"] .founders__img { aspect-ratio: 4 / 3; }
  [data-page="home"] .founders__img img { object-position: 50% 30%; }
  .proof__top { padding-top: 6px; }
  .proof__count { order: 3; flex-basis: 100%; }
  .proof__img { aspect-ratio: 3 / 1; }
  .proof__more li { padding-block: 10px; }
  .choose .ask.ask--light { padding: 18px; }
  .choose .ask__label { margin-bottom: 10px; font-size: .9375rem; }
  .choose .ask textarea { min-height: 60px; }
}

/* The project page (src/pages/project.mjs). */
.project__in { max-width: 680px; display: grid; gap: 18px; }
.project__state { display: grid; gap: 8px; }
.project__state > * { margin: 0; }
.project__h { color: var(--ink); font-weight: 600; }
.project__test { display: inline-block; justify-self: start; padding: 6px 10px; border-radius: 10px; background: rgba(var(--ink-rgb), .06); color: var(--ink-2); font-size: .875rem; }
.project__plan { padding: 18px 20px; border-radius: 18px; background: var(--surface); box-shadow: var(--shadow-card); }
.project__plan > * { margin: 0 0 8px; }
.project__list { padding-inline-start: 1.2em; }

/* The rest of a product's inclusions (Phase 6): a labelled control under the first four. */
.pd-more { margin-top: 12px; }
.pd-more > summary { cursor: pointer; display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; color: var(--accent); }
.pd-more[open] > summary { margin-bottom: 8px; }
/* A project's features: the disclosure is its heading. */
.ind-fold > summary { color: var(--ink); font-size: 1.125rem; letter-spacing: var(--trk-head); }
/* On a wide screen these lists are simply shown, as before: open, and with no control above the rest of the list. */
@media (min-width: 900px) {
  .pd-more--rest { margin-top: 0; }
  .pd-more--rest > summary { display: none; }
  .ind-fold > summary { pointer-events: none; list-style: none; }
  .ind-fold > summary::-webkit-details-marker { display: none; }
  .ind-fold .fold-n { display: none; }
}

/* A product chosen for comparison that the goal hides (Phase 6). */
.cmp-kept { margin: 0 0 16px; display: grid; gap: 6px; }
.cmp-kept ul { list-style: none; padding: 0; display: grid; gap: 2px; }
.cmp-kept .js-kept-x { min-height: 44px; }
