/* Contact (tools/standalone/contact.cjs; behaviour in bodies-contact.js). The letter is written on a pane of frosted
   glass standing over the page's own painting: the hero's picture carries on behind the body, deepened, and meets the
   paper only at the ending. Glass needs something to frost, so the room keeps the painting under it the whole way.
   The body opts out of the shared hand-off (data-handoff="own" on .b-ct): this file owns how it meets the hero. */
[data-topic="contact"] {
  --b-bg: #07090c;   /* the room's ground: the header's strip while the room passes beneath it (data-header="deep") */
  --ct-text: #f3f4f5;
  --ct-label: rgba(237, 241, 244, .7);
  --ct-quiet: rgba(237, 241, 244, .6);
  --ct-line: rgba(237, 241, 244, .24);
  --ct-light: #eaf3fa;
  --ct-ok: #2fc46f;     /* sent: the green check */
  --ct-steel: #9cc3e0;
  --ct-wrong: #f2808e;
  --ct-r: 6px;
}
/* no paper until the ending: the painting shows through the body */
[data-topic="contact"] .t-body { background: transparent; }

/* the room: the painting, held still on the screen while the letter passes over it. Its copy of the painting sits a
   screen above the room's own top (the negative margin) and sticks, so it covers the whole screen as soon as the room
   arrives; bodies-contact.js fades it in as the room rises and keeps it in register with the hero's camera */
.b-ct-room { position: relative; display: flow-root; color: var(--ct-text); color-scheme: dark; }
.b-ct-sky { position: sticky; top: 0; height: max(100vh, 560px); margin-top: calc(-1 * max(100vh, 560px)); overflow: hidden; pointer-events: none; opacity: 0; }
.b-ct-sky-img { position: absolute; inset: -7% -4%; background-size: cover; background-position: var(--vt-pos, 50% 50%); will-change: transform; }
/* deepened: the hero's own shading, then a dusk over all of it, deepest where the letter's words stand */
.b-ct-sky::after { content: ""; position: absolute; inset: 0; background:
  linear-gradient(90deg, rgba(7, 9, 12, .5) 0%, rgba(7, 9, 12, .28) 46%, rgba(7, 9, 12, .12) 70%, rgba(7, 9, 12, .3) 100%),
  linear-gradient(180deg, rgba(7, 9, 12, .62) 0%, rgba(7, 9, 12, .3) 30%, rgba(7, 9, 12, .34) 62%, rgba(7, 9, 12, .82) 100%); }

.b-ct-col { position: relative; width: min(620px, calc(100% - 2 * var(--gutter))); margin-left: max(var(--gutter), 7.5vw); padding: 20vh 0 34vh; }

/* the letter's opening, set on the painting */
.b-ct-open .b-lede { margin: 0; max-width: 15ch; text-align: left; color: var(--ct-text); text-shadow: 0 1px 2px rgba(4, 6, 9, .35), 0 0 22px rgba(4, 6, 9, .45); }
.b-ct-open .b-p { margin: 26px 0 0; max-width: 40ch; color: rgba(237, 241, 244, .8); text-shadow: 0 1px 2px rgba(4, 6, 9, .5), 0 0 18px rgba(4, 6, 9, .5); }

/* the pane. The glass is its own layer under the form: the frost (backdrop blur), a faint tint and sheen, and its edge
   drawn by light alone (a brighter top where the light falls, a faint line round the rest), with a soft fall of
   shadow under it because it stands off the painting */
.b-ct-pane { position: relative; z-index: 0; margin-top: 8vh; padding: clamp(30px, 3.2vw, 48px) clamp(26px, 3.2vw, 50px) clamp(28px, 3vw, 44px); }
.b-ct-glass { position: absolute; inset: 0; z-index: 0; overflow: hidden; border-radius: var(--ct-r); pointer-events: none;
  background: linear-gradient(164deg, rgba(255, 255, 255, .09) 0%, rgba(255, 255, 255, .03) 30%, rgba(255, 255, 255, 0) 56%), rgba(16, 19, 26, .3);
  -webkit-backdrop-filter: blur(26px) saturate(1.55); backdrop-filter: blur(26px) saturate(1.55);
  box-shadow: 0 44px 90px -54px rgba(0, 0, 0, .85); }
/* its edge: a hair of light, brightest along the top where the light falls and fading down the sides */
.b-ct-glass::after { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, .3) 0, rgba(255, 255, 255, .1) 90px, rgba(255, 255, 255, .045) 45%, rgba(255, 255, 255, .03) 85%, rgba(255, 255, 255, .07) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); }
/* the light that pools in the glass behind the field in hand (placed by bodies-contact.js) */
.b-ct-pool { position: absolute; left: 0; top: 0; width: 100px; height: 132px; margin-top: -96px; opacity: 0; transform-origin: 0 0; background: radial-gradient(50% 50% at 50% 74%, rgba(156, 195, 224, .15), rgba(156, 195, 224, 0) 74%); transition: transform .62s var(--sys-ease), opacity .45s var(--sys-ease); }
/* a short light that runs once round the edge as the glass frosts, and again when the letter has gone */
.b-ct-rim { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.b-ct-rim rect { x: .5px; y: .5px; rx: var(--ct-r); fill: none; stroke: var(--ct-light); stroke-width: 1.25; stroke-linecap: round; stroke-dasharray: .1 .9; opacity: 0; filter: drop-shadow(0 0 3px rgba(156, 195, 224, .9)); }

.b-ct-form { position: relative; z-index: 1; display: grid; gap: clamp(26px, 3.4vh, 36px); }
.b-ct-field { position: relative; }
.b-ct-field > label { display: block; width: fit-content; font: italic 400 clamp(18px, 1.35vw, 21px)/1.2 var(--sys-accent); color: var(--ct-label); cursor: pointer; transition: color .25s var(--sys-ease); }
.b-ct-field:focus-within > label, .b-ct-field.is-open > label { color: var(--ct-text); }
.b-ct-hint { margin-top: 6px; max-width: 46ch; font: 400 14px/1.45 var(--sys-body); color: var(--ct-quiet); }
/* each field's line, etched in the glass: a hair of light over a hair of shadow. It brightens under the pointer and
   with the focus; a field that still needs something has a crimson line drawn over it */
.b-ct-line { position: relative; margin-top: 8px; }
.b-ct-line::after, .b-ct-line::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; pointer-events: none; transform-origin: 0 50%; }
.b-ct-line::after { background: var(--ct-line); box-shadow: 0 1px 0 rgba(0, 0, 0, .3); transform: scaleX(var(--draw, 1)); transition: background-color .2s var(--sys-ease); }
.b-ct-field:hover .b-ct-line::after { background: rgba(237, 241, 244, .42); }
.b-ct-field:focus-within .b-ct-line::after, .b-ct-field.is-open .b-ct-line::after { background: rgba(237, 241, 244, .62); }
.b-ct-line::before { z-index: 1; background: var(--ct-wrong); transform: scaleX(0); transition: transform .5s var(--sys-ease); }
.b-ct-field.is-wrong .b-ct-line::before { transform: scaleX(1); }

.b-ct-line :is(input, textarea, select) { display: block; width: 100%; margin: 0; padding: 6px 0 12px; border: 0; border-radius: 0; background: none; color: var(--ct-text); font: 300 clamp(20px, 1.55vw, 24px)/1.3 var(--sys-display); letter-spacing: -.005em; caret-color: var(--ct-steel); outline: none; appearance: none; -webkit-appearance: none; }
.b-ct-line textarea { min-height: 7.4em; padding-top: 10px; resize: vertical; font: 400 17px/1.55 var(--sys-body); letter-spacing: -.008em; }
.b-ct-line :is(input, textarea):focus-visible { outline: none; }
/* (an address filled in by the browser keeps the glass, not the browser's own fill) */
.b-ct-line input:-webkit-autofill { -webkit-text-fill-color: var(--ct-text); caret-color: var(--ct-steel); transition: background-color 600000s 0s, color 600000s 0s; }
/* without the script a choice is a plain select on the same line, with a drawn caret */
.b-ct-line select { padding-right: 30px; cursor: pointer; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 8'%3E%3Cpath d='M1 1.4l5.5 5.2 5.5-5.2' fill='none' stroke='%23edf1f4' stroke-width='1.3'/%3E%3C/svg%3E") no-repeat right 2px center / 13px 8px; }
.b-ct-line select option { color: #0d1117; }
.b-ct-line select[hidden] { display: none; }   /* (once the script has made it a combobox, it only carries the value) */

/* the combobox: the choice on its line, and a caret that turns over as its list opens */
.ct-combo { position: relative; display: flex; align-items: center; gap: 14px; padding: 6px 0 12px; font: 300 clamp(20px, 1.55vw, 24px)/1.3 var(--sys-display); letter-spacing: -.005em; color: var(--ct-text); cursor: pointer; outline: none; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
.ct-combo-value { flex: 1; min-width: 0; display: grid; }
.ct-combo-value > span { grid-area: 1 / 1; text-wrap: balance; }
.ct-combo-value.is-empty { color: rgba(237, 241, 244, .5); }
.ct-combo-caret { flex: none; width: 13px; height: 8px; fill: none; stroke: currentColor; stroke-width: 1.3; opacity: .72; transition: transform .26s var(--sys-ease), opacity .2s; }
.ct-combo[aria-expanded="true"] .ct-combo-caret { transform: scaleY(-1); opacity: 1; }
.ct-combo[aria-disabled="true"] { cursor: default; }

/* its list: a second, darker sheet of glass that frosts the form beneath it. It opens downward out of the field's line
   (a wipe and a short drop), its options settle in one after another, and it closes faster than it opens */
.b-ct-field.is-open { z-index: 5; }
.ct-list { position: absolute; z-index: 20; left: -16px; right: -16px; top: calc(100% + 6px); padding: 8px 0; border-radius: var(--ct-r); visibility: hidden; opacity: 0; transform: translateY(-8px);
  clip-path: inset(0 0 100% 0 round var(--ct-r));
  background: linear-gradient(172deg, rgba(255, 255, 255, .085), rgba(255, 255, 255, .02) 42%), rgba(10, 13, 18, .62);
  -webkit-backdrop-filter: blur(22px) saturate(1.5); backdrop-filter: blur(22px) saturate(1.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), inset 0 0 0 1px rgba(255, 255, 255, .07), 0 30px 60px -26px rgba(0, 0, 0, .8);
  transition: opacity .15s var(--sys-ease), transform .15s var(--sys-ease), clip-path .15s var(--sys-ease), visibility 0s linear .15s; }
.ct-list.is-open { visibility: visible; opacity: 1; transform: none; clip-path: inset(-40px -40px -80px -40px round var(--ct-r)); transition: opacity .22s var(--sys-ease), transform .32s var(--sys-ease), clip-path .38s var(--sys-ease), visibility 0s; }
.ct-opt { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; padding: 11px 18px 12px 20px; cursor: pointer; opacity: 0; transform: translateY(5px); transition: opacity .1s, transform .1s; }
.ct-list.is-open .ct-opt { opacity: 1; transform: none; transition: opacity .26s var(--sys-ease) calc(var(--i) * 28ms + 50ms), transform .34s var(--sys-ease) calc(var(--i) * 28ms + 50ms); }
.ct-opt-name { font: 400 16px/1.3 var(--sys-body); letter-spacing: -.01em; color: rgba(243, 244, 245, .84); transition: color .15s; }
.ct-opt-line { grid-column: 1; margin-top: 3px; font: 400 13px/1.42 var(--sys-body); color: rgba(237, 241, 244, .56); text-wrap: pretty; }
.ct-opt.is-active .ct-opt-name, .ct-opt[aria-selected="true"] .ct-opt-name { color: #fff; }
.ct-opt-tick { grid-column: 2; grid-row: 1 / span 2; align-self: center; width: 16px; height: 16px; fill: none; stroke: var(--ct-light); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.ct-opt-tick path { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset .18s; }
.ct-opt[aria-selected="true"] .ct-opt-tick path { stroke-dashoffset: 0; transition: stroke-dashoffset .5s var(--sys-ease) .14s; }
/* the light behind the option in hand: a wash from the left with a bright edge, gliding from option to option */
.ct-list-glow { position: absolute; z-index: 0; left: 0; right: 0; top: 0; height: 100px; transform-origin: 0 0; pointer-events: none; background: linear-gradient(90deg, rgba(156, 195, 224, .2), rgba(156, 195, 224, .07) 58%, rgba(156, 195, 224, 0)); transition: transform .24s var(--sys-ease); }
.ct-list-glow::before { content: ""; position: absolute; left: 0; top: 20%; bottom: 20%; width: 2px; border-radius: 1px; background: var(--ct-light); box-shadow: 0 0 8px rgba(156, 195, 224, .85); }

.b-ct-err { margin-top: 9px; font: 400 14.5px/1.4 var(--sys-body); color: var(--ct-wrong); }
.b-ct-err[hidden] { display: none; }

/* the light that goes with the focus: it draws along the first line the reader comes to, then glides to each next one
   (bodies-contact.js); crimson over a field that still needs something */
.b-ct-glint { position: absolute; z-index: 3; left: 0; top: 0; width: 100px; height: 2px; margin-top: -1.5px; pointer-events: none; opacity: 0; transform-origin: 0 50%;
  background: linear-gradient(90deg, rgba(207, 227, 241, 0), var(--ct-light) 16%, #fff 50%, var(--ct-light) 84%, rgba(207, 227, 241, 0));
  box-shadow: 0 0 12px 1px rgba(156, 195, 224, .5); transition: transform .58s var(--sys-ease), opacity .35s var(--sys-ease); }
.b-ct-glint > i { position: absolute; inset: 0; opacity: 0; background: linear-gradient(90deg, rgba(242, 128, 142, 0), #f6a3ad 16%, #ffd0d5 50%, #f6a3ad 84%, rgba(242, 128, 142, 0)); box-shadow: 0 0 12px 1px rgba(242, 128, 142, .55); transition: opacity .3s; }
.b-ct-glint.is-wrong > i { opacity: 1; }

/* first-party spam check: a field no person sees or reaches */
.b-ct-trap { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* Send. Its fill is a layer of its own, so while the letter goes the button turns to glass and a light runs round its
   edge; once it has gone it says Sent beside a green check */
.b-ct-send { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 26px; margin-top: 6px; }
.b-ct-go { position: relative; z-index: 0; min-width: 132px; justify-content: center; gap: 9px; border: 0; background: transparent; color: var(--sys-graphite); }
.b-ct-go::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--ct-text); transition: opacity .45s var(--sys-ease), background-color .18s var(--sys-ease); }
.b-ct-go:hover { background: transparent; }
.b-ct-go:hover::before { background: #fff; }
.b-ct-go:focus-visible { outline-color: var(--ct-light); }
.b-ct-go-say { display: grid; }
.b-ct-go-say > span { grid-area: 1 / 1; }
.b-ct-go-run { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.b-ct-go-run rect { x: .75px; y: .75px; width: calc(100% - 1.5px); height: calc(100% - 1.5px); rx: 24.25px; fill: none; stroke: var(--ct-light); stroke-width: 1.25; stroke-linecap: round; stroke-dasharray: .16 .84; opacity: 0; transition: opacity .4s var(--sys-ease); }
.b-ct-go-tick { display: none; width: 20px; height: 20px; margin-right: -6px; overflow: visible; }
.b-ct-go-tick circle { fill: var(--ct-ok); transform-box: fill-box; transform-origin: center; transform: scale(0); }
.b-ct-go-tick path { fill: none; stroke: #fff; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
[data-state="sending"] .b-ct-go, [data-state="sent"] .b-ct-go { color: var(--ct-text); cursor: default; }
[data-state="sending"] .b-ct-go::before, [data-state="sent"] .b-ct-go::before { opacity: .1; }
[data-state="sending"] .b-ct-go-run rect { opacity: 1; animation: ct-run 1.25s linear infinite; }
[data-state="sent"] .b-ct-go-run rect { stroke: var(--ct-ok); opacity: .7; stroke-dasharray: none; }
[data-state="sent"] .b-ct-go-tick { display: block; }
[data-state="sent"] .b-ct-go-tick circle { animation: ct-pop .42s cubic-bezier(.34, 1.56, .64, 1) .08s forwards; }
[data-state="sent"] .b-ct-go-tick path { animation: ct-draw .5s var(--sys-ease) .3s forwards; }
@keyframes ct-run { from { stroke-dashoffset: 0; } to { stroke-dashoffset: -1; } }
@keyframes ct-draw { to { stroke-dashoffset: 0; } }
@keyframes ct-pop { to { transform: scale(1); } }
.b-ct-note { flex: 1 1 250px; max-width: 44ch; font: 400 14px/1.45 var(--sys-body); color: var(--ct-quiet); }
/* the letter, once sent, settles where it was written */
.b-ct-form :is(.b-ct-field) { transition: opacity .8s var(--sys-ease); }
[data-state="sent"] .b-ct-field { opacity: .5; }

.b-ct-direct { margin-top: 6vh; max-width: 44ch; font: 400 15px/1.6 var(--sys-body); color: rgba(237, 241, 244, .72); text-shadow: 0 1px 2px rgba(4, 6, 9, .5); }
.b-ct-direct .mail { font-size: inherit; color: var(--ct-text); background-image: linear-gradient(rgba(239, 238, 233, .42), rgba(239, 238, 233, .42)); }
.b-ct-direct .mail:hover { color: #fff; background-image: linear-gradient(#fff, #fff); }
.b-ct-room :focus-visible { outline-color: var(--ct-light); }

/* the ending: the paper rises over the painting on a long soft edge, so the picture dissolves into it with no box */
[data-topic="contact"] .t-end { margin-top: -30vh; padding-top: calc(30vh + 84px); min-height: calc(100svh + 30vh);
  background: linear-gradient(180deg, rgba(237, 241, 244, 0) 0, rgba(237, 241, 244, .05) 4vh, rgba(237, 241, 244, .16) 9vh, rgba(237, 241, 244, .34) 14vh, rgba(237, 241, 244, .58) 19vh, rgba(237, 241, 244, .82) 24vh, var(--sys-ice) 30vh); }
.b-ct-close .b-h { font-size: clamp(40px, 4.6vw, 88px); }

@media (max-width: 760px) {
  .b-ct-sky-img { background-position: 84% 50%; }   /* the hero's own slice on a phone: the dish */
  .b-ct-sky::after { background: linear-gradient(180deg, rgba(7, 9, 12, .6) 0%, rgba(7, 9, 12, .38) 32%, rgba(7, 9, 12, .42) 64%, rgba(7, 9, 12, .84) 100%); }
  .b-ct-col { width: auto; margin: 0 var(--gutter); padding: 15vh 0 30vh; }
  .b-ct-pane { margin-top: 6vh; padding: 26px 20px 24px; }
  .ct-list { left: -12px; right: -12px; }
  .ct-opt { padding: 12px 16px 13px 18px; }
  .b-ct-send { gap: 14px 20px; }
  [data-topic="contact"] .t-end { padding-top: calc(30vh + 78px); }
}
@media (prefers-reduced-motion: reduce) {
  .b-ct-pool, .b-ct-glint, .b-ct-glint > i, .ct-list, .ct-list.is-open, .ct-opt, .ct-list.is-open .ct-opt, .ct-list-glow, .ct-combo-caret, .ct-opt-tick path, .b-ct-line::before, .b-ct-go::before, .b-ct-go-run rect, .b-ct-form .b-ct-field { transition: none !important; }
  [data-state="sending"] .b-ct-go-run rect { animation: none; stroke-dasharray: none; opacity: .6; }
  [data-state="sent"] .b-ct-go-tick path { animation: none; stroke-dashoffset: 0; }
  [data-state="sent"] .b-ct-go-tick circle { animation: none; transform: none; }
}
