html{background:var(--ink-900)}
body{margin:0;background:var(--ink-900);color:#fff;font-family:var(--font-sans);-webkit-font-smoothing:antialiased;overflow-x:hidden}
a{color:var(--lime-300);text-decoration:underline;text-underline-offset:3px}a:hover{color:#fff}
button{font:inherit;color:inherit}
::selection{background:var(--lime-300);color:var(--ink-900)}
.rv{opacity:0;transform:translateY(48px);transition:opacity 1s var(--ease-out-expo),transform 1s var(--ease-out-expo);transition-delay:var(--d,0ms)}
.rv.in{opacity:1;transform:none}
.line{display:block;overflow:hidden;padding-bottom:.1em;margin-bottom:-.1em}
.line>span{display:inline-block;animation:rd-rise 1.2s var(--ease-out-expo) both;animation-delay:var(--d,0ms)}
.soc{cursor:pointer;display:block}.soc:hover{transform:scale(1.18) rotate(-8deg)}
.ghost-btn{cursor:pointer;transition:transform .5s var(--ease-out-back),background .3s}.ghost-btn:hover{transform:scale(1.06)}
/* Contact form rows: hover hints (lit edge, brighter number); the row being answered gets a full lime edge, a tinted wash,
   a filled number and the underline, while the other rows step back. A tick appears once a row has an answer. */
.field{position:relative;border:1px solid var(--white-a20);border-top-width:0;transition:background .5s var(--ease-out-expo),opacity .5s var(--ease-out-expo)}
.fields>:first-child .field{border-top-width:1px}
.field::before{content:'';position:absolute;left:-1px;top:0;bottom:0;width:3px;background:var(--lime-300);box-shadow:0 0 16px var(--lime-a50);transform:scaleY(0);transition:transform .7s var(--ease-out-expo)}
.field::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--lime-300);transform:scaleX(0);transform-origin:left;transition:transform .9s var(--ease-out-expo)}
.field:hover{background:rgba(255,255,255,.025)}
.field:hover::before{transform:scaleY(.3)}
.field:focus-within{background:linear-gradient(90deg,rgba(225,255,187,.08),rgba(225,255,187,0) 75%)}
.field:focus-within::before{transform:scaleY(1)}
.field:focus-within::after{transform:scaleX(1)}
.fields:focus-within .field:not(:focus-within){opacity:.45}
.field .n{position:absolute;left:30px;top:64px;min-width:36px;height:24px;padding:0 9px;box-sizing:border-box;border-radius:12px;border:1px solid var(--white-a20);display:grid;place-items:center;font:500 12px/1 var(--font-nav);letter-spacing:.06em;color:var(--white-a50);transition:background .4s,color .4s,border-color .4s}
.field:hover .n{border-color:var(--white-a50);color:#fff}
.field:focus-within .n{background:var(--lime-300);border-color:var(--lime-300);color:var(--ink-900)}
.field:focus-within .q{color:var(--lime-300)}
.field .ok{position:absolute;right:28px;top:62px;width:28px;height:28px;border-radius:50%;background:var(--lime-300);color:var(--ink-900);display:grid;place-items:center;opacity:0;transform:scale(.4);transition:opacity .4s,transform .6s var(--ease-spring,cubic-bezier(.34,1.56,.64,1))}
.field:has(input:not(:placeholder-shown)) .ok,.field:has(textarea:not(:placeholder-shown)) .ok{opacity:1;transform:none}
.field input,.field textarea{background:none;border:0;outline:0;color:#fff;font:600 20px/1.2 var(--font-form);letter-spacing:-0.01em;padding:0;width:100%;resize:none}
.field input::placeholder,.field textarea::placeholder{color:var(--white-a40)}
@keyframes rd-row-in{from{opacity:0;transform:translateY(40px)}to{opacity:1;transform:none}}
.noscroll{scrollbar-width:none}.noscroll::-webkit-scrollbar{display:none}

.ftf{width:100%;border:0;outline:0;background:transparent;font:400 24px/1.3 var(--font-sans);letter-spacing:-0.02em;color:var(--ink-900);padding:0;resize:none;display:block}.ftf::placeholder{color:var(--ink-a40)}
.pin-link{color:inherit;text-decoration:none;justify-self:start;transition:color .35s var(--ease-out-expo)}.pin-link:hover{color:var(--lime-300)}.xp-row:focus-visible{outline:2px solid var(--lime-300);outline-offset:-2px}
/* Hidden while the preloader runs: its rounded bottom-left corner shows this part of the hero underneath. */
html.rd-intro .rd-intro-hide{visibility:hidden}
/* Footer form: the contact-row idea tuned for the white footer (teal, since lime is too faint on white). The field being typed in
   gets a teal dot and darker label with the teal underline; the other fields step back; a teal tick marks answered fields. */
.ff{isolation:isolate;transition:opacity .5s var(--ease-out-expo)}
.ff::before{content:'';position:absolute;inset:-14px -18px 0;z-index:-1;border-radius:14px 14px 0 0;background:linear-gradient(to top,rgba(0,153,144,.09),rgba(0,153,144,0));opacity:0;transition:opacity .5s var(--ease-out-expo)}
.ff.on::before{opacity:1}
.ff-l{display:flex;align-items:center;gap:0;color:var(--ink-a40);transition:color .4s,gap .5s var(--ease-out-expo)}
.ff-l::before{content:'';width:0;height:7px;border-radius:4px;background:var(--glow-teal);transition:width .5s var(--ease-out-expo)}
.ff-b{background:var(--ink-a20);transition:background .3s}
.ff:hover .ff-l{color:var(--ink-a90)}
.ff:hover .ff-b{background:var(--ink-a40)}
.ff.on .ff-l{color:var(--ink-900);gap:8px}
.ff.on .ff-l::before{width:7px}
.ffields:focus-within .ff:not(.on){opacity:.4}
.ff.done .ftf{padding-right:32px;box-sizing:border-box}
.ff-ok{position:absolute;right:0;bottom:18px;width:22px;height:22px;border-radius:50%;background:var(--glow-teal);color:#fff;display:grid;place-items:center;opacity:0;transform:scale(.4);transition:opacity .4s,transform .6s var(--ease-spring,cubic-bezier(.34,1.56,.64,1))}
.ff.done .ff-ok{opacity:1;transform:none}
/* Where people type, show the normal text cursor: the custom one shrinks to a thin lime bar that is easy to miss (and vanishes on white). */
html.rd-no-cursor .field,html.rd-no-cursor .field *,html.rd-no-cursor .ff,html.rd-no-cursor .ff *{cursor:text!important}
.rd-cur[data-mode=text] .rd-cur-dot,.rd-cur[data-mode=text] .rd-cur-ring{opacity:0}
/* Project page live-site link */
.rd-live{color:var(--lime-300);text-decoration:none;display:inline-flex;align-items:center;gap:8px;background:linear-gradient(currentColor,currentColor) 0 100%/0 1px no-repeat;transition:background-size .6s var(--ease-out-expo)}
.rd-live:hover{background-size:100% 1px}
.rd-live span{display:inline-block;transition:transform .5s var(--ease-out-expo)}.rd-live:hover span{transform:translate(3px,-3px)}
/* Download CV: once the disc has rolled over, the arrow keeps dropping into the file while the pill is hovered or focused. */
@keyframes rd-dl-drop{0%,100%{transform:none;opacity:1}42%{transform:translateY(5px);opacity:0}43%{transform:translateY(-5px);opacity:0}}
.rd-dl:hover .rd-dl-a,.rd-dl:focus-visible .rd-dl-a{animation:rd-dl-drop 1.4s .75s var(--ease-in-out-quart) infinite}
/* Testimonials book: a teal drop cap opens each quote, and a page darkens as it turns past upright. */
.rd-book-q::first-letter{float:left;font:normal 700 68px/.78 var(--font-sans);color:var(--glow-teal);margin:8px 12px 0 0}
@keyframes rd-page-shade{0%,100%{opacity:0}50%{opacity:.3}}
@keyframes rd-book-timer{from{stroke-dashoffset:182.2}to{stroke-dashoffset:0}}
/* Form errors: the field's line turns red and a short note says what's missing. */
:root{--danger:rgb(214,69,65)}
.ff.bad .ff-b{background:var(--danger)}
.ff.bad .ff-l{color:var(--danger)}
.ff-e{position:absolute;left:0;top:100%;margin-top:6px;font:400 12px/1 var(--font-sans);color:var(--danger)}
.field.bad::after{transform:scaleX(1);background:var(--danger)}
.field.bad .q{color:var(--danger)}
.field .err-t{position:absolute;left:94px;top:178px;font:400 14px/1 var(--font-sans);color:var(--danger)}
/* "Let’s work together": the apostrophe alone is set smaller, so it doesn't loom over the big bold heading. */
.rd-lwt .rd-kt-r[data-ch="’"]{font-size:.6em;position:relative;top:-.46em;margin-left:.08em}
/* Battery: a section out of view holds its CSS animations (App.jsx toggles .rd-off). */
.rd-off,.rd-off *{animation-play-state:paused!important}
/* Hidden "404" tag beside the contact email: faint until you hover or focus it, then it glitches like the 404 page and an arrow slides out */
.egg{display:inline-flex;align-items:center;flex:none;padding:4px 7px 3px;border-radius:6px;font:500 10px/1 var(--font-nav);letter-spacing:.16em;color:var(--white-a20);box-shadow:inset 0 0 0 1px var(--white-a10,rgba(255,255,255,.1));text-decoration:none;transition:color .35s var(--ease-out-expo),box-shadow .35s var(--ease-out-expo),transform .35s var(--ease-out-back)}
.egg::after{content:'\2197';display:inline-block;max-width:0;margin-left:0;overflow:hidden;opacity:0;transition:max-width .3s var(--ease-out-expo),margin .3s var(--ease-out-expo),opacity .3s}
.egg:hover,.egg:focus-visible{color:var(--lime-300);box-shadow:inset 0 0 0 1px var(--lime-a50);text-shadow:-1px 0 #00b3a8,1px 0 #ff6b57;transform:rotate(-4deg);outline:none}
.egg:hover::after,.egg:focus-visible::after{max-width:12px;margin-left:5px;opacity:1}
/* Seam tapes between the page and the white footer (Footer.jsx SeamTapes). Desktop sizes are in the 1532px design; compact.css retunes them. */
.rd-seam{position:relative;z-index:3;height:0;pointer-events:none}
.rd-seam-clip{position:absolute;left:0;right:0;top:-90px;height:180px;overflow:hidden}
.rd-tape{position:absolute;left:-4%;width:108%;top:calc(50% - 28px)}
.rd-tape.a{transform:rotate(1.8deg)}.rd-tape.b{transform:rotate(-1.8deg)}
.rd-tape .rd-mq{padding:18px 0;font:700 20px/1 var(--font-sans);letter-spacing:-0.02em;text-transform:uppercase}
.rd-tape .rd-mq{--mq-gap:1.7em!important}.rd-tape-sep{width:1em!important;height:1em!important}
.rd-tape.a .rd-mq{background:var(--ink-900);color:#fff;box-shadow:0 0 0 1px rgba(255,255,255,.1)}
.rd-tape.b .rd-mq{background:var(--lime-300);color:var(--ink-900)}
