/* nickmccally.com: the v5b "dock" design (Personal Site (2)/Nickolas McCally v5b -dock-.html,
   nm-core.css), fixed to its Dark mode and Soft light tweaks (owner 2026-11-13). */
@font-face{font-family:"Geist";src:url("fonts/Geist-Variable.woff2") format("woff2");font-weight:100 900;font-style:normal;font-display:swap}
:root{color-scheme:dark;--bg:#131416;--ink:#F2F1EE;--ink2:#ABADB1;--ink3:#76787D;--hair:#26282B;--surface:#1C1D20;--accent:#F2F1EE;--onAccent:#131416;--danger:#FF8577;--edge:rgba(0,0,0,.28);--shadow:0 0 0 1px rgba(255,255,255,.05),0 24px 60px -20px rgba(0,0,0,.55);--wash:color-mix(in oklab,var(--ink) 6%,transparent);--hair2:color-mix(in oklab,var(--ink) 20%,transparent);--ease:cubic-bezier(.32,.72,0,1)}
*{box-sizing:border-box}
html,body{margin:0;background:var(--bg);color:var(--ink)}
body{font-family:"Geist",ui-sans-serif,system-ui,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
a{color:var(--ink);text-decoration:none}a:hover{color:var(--ink2)}
::selection{background:var(--ink);color:var(--bg)}
.nm{display:block;color:var(--accent)}
.btn{height:52px;padding:0 26px;border-radius:999px;border:0;font:inherit;font-size:16px;font-weight:500;letter-spacing:-0.012em;display:inline-flex;align-items:center;justify-content:center;gap:7px;cursor:pointer;white-space:nowrap;transition:transform .2s var(--ease),background .25s,color .25s,opacity .25s,box-shadow .25s}
.btn:active:not(:disabled){transform:scale(.96)}
.btn.primary{background:var(--accent);color:var(--onAccent)}
.btn.primary:hover:not(:disabled){background:color-mix(in oklab,var(--accent) 86%,var(--bg));color:var(--onAccent)}
.btn.secondary{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 1px var(--hair2)}
.btn.secondary:hover{background:var(--wash);color:var(--ink)}
.btn svg{transition:transform .35s var(--ease)}.btn.secondary:hover svg{transform:translate(2px,-2px)}
.btn.sm{height:40px;padding:0 20px;font-size:15px}
.btn:disabled{opacity:.18;cursor:default}
.card{display:flex;flex-direction:column;animation:paneIn .45s cubic-bezier(.2,.8,.2,1) both}
@keyframes paneIn{from{opacity:0;transform:translateY(6px);filter:blur(4px)}to{opacity:1;transform:none;filter:none}}
.card-head{display:flex;justify-content:space-between;align-items:center;padding:12px 12px 0 24px;font-size:14px;font-weight:500;color:var(--ink2)}
.card-head.no-x{min-height:48px;padding-right:24px}
textarea::placeholder,input::placeholder{color:var(--ink3);opacity:1}
.card-foot{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:10px 10px 10px 24px;border-top:1px solid var(--hair)}
.link-sm{display:inline-flex;align-items:center;gap:6px;border:0;background:transparent;padding:6px 0;font:inherit;font-size:14px;font-weight:500;color:var(--ink2);cursor:pointer;transition:color .2s}
.link-sm:hover{color:var(--ink)}
.quote{display:flex;gap:16px;align-items:flex-start;padding:6px 20px 14px 24px}
.quote .row-lbl{line-height:22px}
.row{display:flex;align-items:center;gap:16px;padding:0 24px;cursor:text}
.row-lbl{flex:0 0 64px;font-size:14px;font-weight:500;letter-spacing:-0.006em;color:var(--ink2);transition:color .2s}
.fieldwrap.err .row-lbl{color:var(--danger)}
.quote p{margin:0;flex:1;font-size:15px;line-height:22px;color:var(--ink2);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;white-space:pre-wrap;overflow-wrap:anywhere}
.fieldwrap{border-top:1px solid var(--hair);transition:background .25s}
.fieldwrap.err{background:color-mix(in oklab,var(--danger) 8%,transparent);border-top-color:color-mix(in oklab,var(--danger) 35%,var(--hair))}
.fieldwrap.err+.fieldwrap,.fieldwrap.err+.card-foot{border-top-color:color-mix(in oklab,var(--danger) 35%,var(--hair))}
.fieldwrap.shake{animation:shake .42s cubic-bezier(.36,.07,.19,.97)}
@keyframes shake{20%{transform:translateX(-6px)}40%{transform:translateX(5px)}60%{transform:translateX(-3px)}80%{transform:translateX(2px)}}
.field-err{display:flex;align-items:flex-start;gap:7px;margin:-8px 0 0;padding:0 24px 14px 104px;font-size:14px;line-height:19px;font-weight:500;color:var(--danger);animation:errIn .3s cubic-bezier(.2,.8,.2,1) both}
.field-err svg{flex:0 0 auto;margin-top:2px}
/* A send that failed on the server side (rate limit, relay down): one line above the buttons. */
.form-err{margin:0;padding:12px 24px 14px;border-top:1px solid color-mix(in oklab,var(--danger) 35%,var(--hair))}
@keyframes errIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.btn.back{padding:0 18px 0 14px;gap:5px}
.btn.back:hover svg{transform:translateX(-2px)}
.field{display:block;flex:1;min-width:0;width:100%;height:56px;border:0;outline:0;background:transparent;color:var(--ink);font:inherit;font-size:17px;letter-spacing:-0.012em;padding:0}
.fieldwrap:not(.err):focus-within{background:var(--wash)}
.sent{display:flex;align-items:center;gap:14px;padding:14px 24px 22px}
.tick{width:40px;height:40px;border-radius:50%;background:var(--accent);color:var(--onAccent);display:grid;place-items:center;flex:0 0 auto;animation:pop .5s cubic-bezier(.3,1.5,.5,1) both}
@keyframes pop{from{transform:scale(.4);opacity:0}to{transform:none;opacity:1}}
.sent-copy{display:flex;flex-direction:column;gap:2px;min-width:0;font-size:16px;letter-spacing:-0.01em}
.sent-copy span{color:var(--ink2);overflow:hidden;text-overflow:ellipsis}
/* The honeypot: off screen for people, still in the form for bots. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
textarea:focus-visible,.field:focus-visible{outline:none}
@media (prefers-reduced-motion:no-preference){
html:not(.settled) .draw .nm-ring{stroke-dasharray:1 1;stroke-dashoffset:1;animation:drawRing 1.5s cubic-bezier(.65,0,.35,1) .1s forwards}
html:not(.settled) .draw .nm-letters{stroke-dasharray:1;stroke-dashoffset:1;animation:draw 1.5s cubic-bezier(.65,0,.35,1) .65s forwards}
html:not(.settled) .r{opacity:0;animation:fadeUp .9s cubic-bezier(.2,.8,.2,1) forwards}
html:not(.settled) .r1{animation-delay:.9s}html:not(.settled) .r2{animation-delay:1.02s}html:not(.settled) .r3{animation-delay:1.14s}html:not(.settled) .r4{animation-delay:1.3s}
}
@keyframes draw{to{stroke-dashoffset:0}}
/* The ring is a CLOSED path: at dashoffset 0 the dash ends exactly where it begins, and butt
   caps leave a hairline of background at 12 o'clock -- a black dot that sat there from 1.6s
   (draw ends) until 3s (.settled drops the dash). Collapse the gap at the very end, once the
   stroke already covers the whole circle, so the ends overlap instead of abutting. Nothing
   about the draw itself changes: dashoffset still reaches 0 on the same curve. */
@keyframes drawRing{99%{stroke-dashoffset:0;stroke-dasharray:1 1}to{stroke-dashoffset:0;stroke-dasharray:1 0}}
@keyframes fadeUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* The dock page (v5b). */
.dk{min-height:100svh;display:flex;flex-direction:column;padding:32px 22px 140px}
.dk-light{position:fixed;inset:0;pointer-events:none;z-index:0;opacity:0;transition:opacity 1.2s ease;background:radial-gradient(56% 48% at 50% 40%,var(--surface) 0%,color-mix(in oklab,var(--surface) 45%,transparent) 42%,transparent 72%),radial-gradient(110% 95% at 50% 40%,transparent 38%,var(--edge) 100%)}
.dk.lit .dk-light{opacity:1}
.dk-mark .nm{transition:filter .8s ease}
@media (prefers-reduced-motion:no-preference){html:not(.settled) .dk.lit .dk-light{animation:lightIn 2s ease .4s both}}
@keyframes lightIn{from{opacity:0}to{opacity:1}}
.dk-center{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}
.dk-mark{width:clamp(140px,15vw,220px);margin-bottom:clamp(32px,5vh,48px)}
.dk-mark .nm{width:100%;height:auto}
.dk-name{margin:0;font-size:clamp(34px,4vw,56px);font-weight:600;line-height:1;letter-spacing:-0.04em}
.dk-li{margin-top:clamp(28px,4vh,44px)}
.dk-role{margin:16px 0 0;max-width:34ch;text-wrap:balance;line-height:1.4;font-size:clamp(16px,1.3vw,19px);font-weight:500;letter-spacing:-0.014em;color:var(--ink2)}
.dk-dockwrap{position:fixed;left:0;right:0;bottom:max(20px,env(safe-area-inset-bottom));display:flex;justify-content:center;padding:0 16px;z-index:10;pointer-events:none}
.dock{pointer-events:auto;width:min(620px,100%);background:color-mix(in oklab,var(--surface) 80%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.5);backdrop-filter:blur(24px) saturate(1.5);box-shadow:var(--shadow);border-radius:32px;position:relative;overflow:hidden;transition:height .55s var(--ease),border-radius .55s var(--ease)}
.dock.tall{border-radius:24px}
.dock::after{content:"";position:absolute;inset:0;z-index:2;border-radius:inherit;pointer-events:none;box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ink) 8%,transparent);transition:box-shadow .25s}.dock:focus-within::after{box-shadow:inset 0 0 0 1.5px var(--accent)}
.dock-bar{display:flex;align-items:flex-end;gap:8px;padding:8px;animation:paneIn .45s cubic-bezier(.2,.8,.2,1) both}
.dock-bar textarea{flex:1;min-width:0;border:0;outline:0;resize:none;background:transparent;color:var(--ink);font:inherit;font-size:17px;line-height:24px;letter-spacing:-0.012em;padding:12px 0 12px 16px}
.dock-go{flex:0 0 auto;width:48px;height:48px;border-radius:50%;border:0;background:var(--accent);color:var(--onAccent);display:grid;place-items:center;cursor:pointer;transition:opacity .25s,transform .2s var(--ease)}
.dock-go:disabled{opacity:.16;cursor:default}.dock-go:active:not(:disabled){transform:scale(.92)}
.dock .card{background:transparent}
@media (max-width:480px){.dock-bar textarea{padding-left:12px}}
/* Phones: "Message Nickolas" fits on one line (17px wraps at 375px wide). 16px keeps iOS from
   zooming on focus. */
@media (max-width:480px){.dock-bar{gap:6px}.dock-bar textarea{font-size:16px;padding-left:10px}}

/* Shown only without JavaScript: the name and role, centred. */
.ns{min-height:100vh}
