2026-10-04 02:44:52 +00:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< title > Persimmons — Passwords, PATs & Plenty of P's</ title >
< meta name = "description" content = "Useful P's for humans + agents." >
< link rel = "icon" href = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🍊</text></svg>" >
< style >
: root { --ink : #241a14 ; --muted : #75675e ; --line : #eadfd6 ; --paper : #fffdfa ; --soft : #fff5ea ; --orange : #f47b20 ; --orange2 : #dc6916 ; --green : #2f7d4a ; --red : #a23b2a ; --shadow : 0 20 px 56 px rgba ( 83 , 48 , 23 , .075 )}
* { box-sizing : border-box } [ hidden ] { display : none !important } html , body { margin : 0 ; min-height : 100 % ; background : var ( -- paper ); color : var ( -- ink ); font-family : ui-sans-serif , - apple-system , BlinkMacSystemFont , "Segoe UI" , sans-serif }
body { padding : 24 px } main { width : min ( 980 px , 100 % ); margin : auto ; padding : 30 px 0 64 px }
. row , . actions , . cardtop , . shellTop , . groupHead , . choicegrid { display : flex ; align-items : center }
. hero { padding : 18 px 0 36 px ; text-align : center }. heroInner { width : min ( 900 px , 100 % ); margin : 0 auto }. hero h1 { display : grid ; row-gap : .045 em ; margin : 0 ; font-size : clamp ( 40 px , 6 vw , 68 px ); line-height : .9 ; letter-spacing : -.052 em }
. hero h1 span { display : block }. heroName , . heroPermissions , . heroPromise { font-size : 1 em ; line-height : .9 }. heroName , . heroPromise { font-family : ui-sans-serif , - apple-system , BlinkMacSystemFont , "Segoe UI" , sans-serif ; font-weight : 800 ; letter-spacing : -.052 em }. heroFruit { display : inline !important ; font-size : .62 em ; vertical-align : .08 em ; margin-right : .08 em }. heroPermissions { color : var ( -- orange ); font-family : Georgia , "Times New Roman" , serif ; font-style : italic ; font-weight : 600 ; letter-spacing : -.035 em ; margin : 0 }. heroPromise { color : var ( -- ink )}
. heroFlow { margin-top : 28 px ; font-size : clamp ( 40 px , 6 vw , 68 px ); line-height : 1.2 }. pLine { margin : 0 0 8 px ; font-size : clamp ( 17 px , 2 vw , 21 px ); font-weight : 730 ; letter-spacing : -.018 em }. lede { margin : 0 auto ; max-width : 680 px ; color : var ( -- muted ); font-size : 15 px ; line-height : 1.5 }
button , . buttonLink { appearance : none ; border : 1 px solid var ( -- line ); border-radius : 11 px ; background : #fff ; padding : 9 px 13 px ; font : inherit ; font-size : 13 px ; font-weight : 730 ; color : var ( -- ink ); cursor : pointer ; text-decoration : none ; display : inline-flex ; align-items : center ; justify-content : center } button : hover , . buttonLink : hover { border-color : #d9c7ba }. primary { background : var ( -- orange ); border-color : var ( -- orange ); color : #fff }. primary : hover { background : var ( -- orange2 ); border-color : var ( -- orange2 )}. ctaOutline { border-color : var ( -- orange ); color : var ( -- orange ); background : #fff }. ctaOutline : hover { border-color : var ( -- orange2 ); color : var ( -- orange2 ); background : var ( -- soft )}. danger { color : var ( -- red )} button : disabled { opacity : .5 ; cursor : default }
. vaultShell { border : 1 px solid var ( -- line ); border-radius : 22 px ; background : #fff ; box-shadow : var ( -- shadow ); overflow : hidden }. shellTop { justify-content : space-between ; gap : 16 px ; padding : 18 px 20 px ; border-bottom : 1 px solid var ( -- line ); background : linear-gradient ( 180 deg , #fff , #fffdfa )}
. shellTop h2 { margin : 0 ; font-size : 20 px ; letter-spacing : -.02 em }. hint { color : var ( -- muted ); font-size : 12 px ; line-height : 1.5 }. shellActions { display : flex ; gap : 8 px ; flex-wrap : wrap }. vaultGroup { padding : 18 px 20 px }. vaultGroup + . vaultGroup { border-top : 1 px solid var ( -- line )}. groupHead { justify-content : space-between ; gap : 16 px ; margin-bottom : 12 px }. groupRule { border-top : 1 px solid var ( -- line ); margin : 0 -20 px 16 px }. groupHead strong { font-size : 15 px }. groupHead . hint { margin-top : 3 px }
. repoControls { min-width : min ( 360 px , 100 % )} select , input , textarea { width : 100 % ; border : 1 px solid var ( -- line ); border-radius : 10 px ; background : #fff ; padding : 10 px 11 px ; font : inherit ; color : var ( -- ink ); outline : none } select : focus , input : focus , textarea : focus { border-color : #f0a36c ; box-shadow : 0 0 0 3 px rgba ( 244 , 123 , 32 , .08 )}
. state { min-height : 18 px ; margin-bottom : 8 px ; color : var ( -- muted ); font-size : 12 px }. state . good { color : var ( -- green )}. state . bad { color : var ( -- red )}. list { display : grid ; gap : 10 px }. empty { padding : 24 px 14 px ; border : 1 px dashed var ( -- line ); border-radius : 13 px ; color : var ( -- muted ); text-align : center ; font-size : 13 px ; line-height : 1.5 }. emptyCta { display : flex ; align-items : center ; justify-content : center ; border : 0 ; padding : 18 px 14 px }
. connection { border : 1 px solid var ( -- line ); border-radius : 14 px ; padding : 14 px ; background : #fff }. cardtop { justify-content : space-between ; gap : 14 px ; align-items : flex-start }. title { font : 760 14 px ui-monospace , SFMono-Regular , Menlo , monospace ; overflow-wrap : anywhere }. account { margin-top : 4 px ; color : var ( -- muted ); font-size : 12 px }. badge { font-size : 12 px ; white-space : nowrap }. badge . active { color : var ( -- green )}. badge . revoked { color : var ( -- red )}
. where { margin-top : 10 px ; color : var ( -- muted ); font-size : 12 px }. mask { margin : 9 px 0 10 px ; padding : 9 px 10 px ; border-radius : 9 px ; background : var ( -- soft ); font : 13 px ui-monospace , SFMono-Regular , Menlo , monospace ; letter-spacing : .04 em }. scope { display : inline-block ; margin : 3 px 4 px 0 0 ; padding : 3 px 7 px ; border : 1 px solid var ( -- line ); border-radius : 999 px ; font-size : 11 px }. meta { margin-top : 8 px ; color : var ( -- muted ); font-size : 12 px ; line-height : 1.5 }. actions { flex-wrap : wrap ; gap : 8 px ; margin-top : 11 px }. rotatebox { display : none ; margin-top : 11 px ; padding-top : 11 px ; border-top : 1 px solid var ( -- line )}. rotatebox . open { display : grid ; grid-template-columns : 1 fr auto ; gap : 8 px }
. scrim { position : fixed ; inset : 0 ; display : grid ; place-items : center ; padding : 18 px ; background : rgba ( 36 , 26 , 20 , .32 ); z-index : 20 }. scrim [ hidden ] { display : none }. composer { width : min ( 660 px , 100 % ); max-height : calc ( 100 vh - 36 px ); overflow : auto ; border : 1 px solid var ( -- line ); border-radius : 20 px ; background : var ( -- paper ); box-shadow : 0 30 px 90 px rgba ( 50 , 30 , 18 , .24 ); padding : 22 px }. composerTop { display : flex ; justify-content : space-between ; gap : 16 px ; align-items : flex-start }. composerTop h2 { margin : 0 ; font-size : 22 px }. close { padding : 6 px 10 px }. step { margin-top : 22 px }. step [ hidden ] { display : none }. stepnum { color : var ( -- orange ); font-size : 12 px ; font-weight : 800 ; text-transform : uppercase ; letter-spacing : .08 em }. question { margin : 6 px 0 14 px ; font-size : 18 px ; font-weight : 760 }
. choicegrid { align-items : stretch ; gap : 10 px ; flex-wrap : wrap }. choice { flex : 1 1 130 px ; flex-direction : column ; align-items : flex-start ; justify-content : center ; text-align : left ; padding : 14 px }. choice strong { display : block ; width : 100 % }. choice small { display : block ; width : 100 % ; margin-top : 4 px ; color : var ( -- muted ); font-weight : 500 ; line-height : 1.25 }. choice . selected { border-color : var ( -- orange ); box-shadow : 0 0 0 2 px rgba ( 244 , 123 , 32 , .1 )}
. field { display : grid ; gap : 6 px ; margin-bottom : 12 px }. field label { font-size : 12 px ; font-weight : 720 ; color : var ( -- muted )}. fieldHelp { margin-top : -2 px ; color : var ( -- muted ); font-size : 11 px }. checks { display : flex ; gap : 8 px ; flex-wrap : wrap }. check { display : flex ; gap : 6 px ; align-items : center ; border : 1 px solid var ( -- line ); border-radius : 999 px ; padding : 7 px 9 px ; font-size : 12 px }. check input { width : auto }. advanced { margin-top : 14 px ; border-top : 1 px solid var ( -- line ); padding-top : 13 px }. advanced summary { cursor : pointer ; font-size : 13 px ; font-weight : 720 }. advanced . inside { margin-top : 12 px }. composerNav { display : flex ; justify-content : space-between ; gap : 10 px ; margin-top : 18 px }
. footerNote { font-weight : 400 ; font-style : normal ; padding : 18 px 12 px 0 ; color : var ( -- muted ); font-size : 11.5 px ; line-height : 1.5 ; text-align : center }. footerNote strong { display : block ; color : var ( -- ink ); margin-bottom : 3 px }. apiP { font-style : italic ; font-weight : inherit }
@ media ( max-width : 720px ) { body { padding : 16 px }. hero { padding-top : 22 px }. shellTop , . groupHead { align-items : flex-start ; flex-direction : column }. shellActions { width : 100 % }. shellActions button { flex : 1 }. repoControls { width : 100 % ; min-width : 0 }. choicegrid { display : grid ; grid-template-columns : 1 fr 1 fr }. rotatebox . open { grid-template-columns : 1 fr }}
2026-10-04 08:05:18 +00:00
. juiceHover { outline : 3 px solid #ed9238 ; background : #fff1df }. connection [ draggable = true ] { cursor : grab }. juiceCard { padding : 12 px ; margin-top : 10 px ; border : 1 px solid var ( -- line ); border-radius : 10 px }. juiceCard p { margin : 6 px 0 ; overflow-wrap : anywhere }
. persimmonsFooter { text-align : center ; margin : 26 px 0 0 ; color : var ( -- muted ); font-size : 12 px ; line-height : 1.5 }. persimmonsFooter strong { display : block ; color : var ( -- ink ); font-size : 13 px ; margin-bottom : 4 px }. vaultFlow { font-size : 15 px ; line-height : 1.4 ; opacity : .72 }
. vaultSummary { display : flex ; align-items : center ; gap : 10 px ; margin-bottom : 12 px }. lockIcon { font-size : 22 px ; line-height : 1 }. vaultCount { color : var ( -- muted ); font-size : 12 px }
. credentialSource { display : flex ; gap : 6 px ; align-items : baseline ; margin-top : 10 px ; color : var ( -- muted ); font-size : 12 px ; overflow-wrap : anywhere }. credentialSource a { color : inherit }. credentialId { font-family : ui-monospace , SFMono-Regular , Menlo , monospace ; text-transform : uppercase }
# namedVaultList { display : grid ; gap : 10 px }. namedVaultCard { padding : 14 px 16 px }. namedVaultMeta { display : flex ; align-items : center ; gap : 8 px ; flex-wrap : wrap ; margin-top : 8 px }. namedVaultBadge { display : inline-flex ; align-items : center ; padding : 3 px 7 px ; border : 1 px solid var ( -- line ); border-radius : 999 px ; color : var ( -- muted ); font-size : 11 px }. namedVaultActions { display : flex ; gap : 8 px ; flex-wrap : wrap ; margin-top : 12 px }. namedVaultBody { margin-top : 12 px ; padding : 14 px ; border : 1 px dashed var ( -- line ); border-radius : 11 px ; color : var ( -- muted ); font-size : 12 px ; line-height : 1.5 }. namedVaultBody strong { display : block ; color : var ( -- ink ); margin-bottom : 3 px }
@ media ( max-width : 720px ) {. vaultSummary { align-items : flex-start }. shellActions . buttonLink , . shellActions button { flex : 1 }}
2026-10-04 02:44:52 +00:00
</ style >
</ head >
< body >
< main >
< section class = "hero" >
< div class = "heroInner" >
2026-10-04 08:05:18 +00:00
< h1 >< span class = "heroName" >< span class = "heroFruit" > 🍊</ span > Persimmons</ span >< span class = "heroPermissions" > permissions</ span >< span class = "heroPromise" > put plainly</ span ></ h1 >
2026-10-04 02:44:52 +00:00
</ div >
</ section >
< section class = "vaultShell" >
< div class = "shellTop" >
2026-10-04 08:05:18 +00:00
< div >< h2 > Master vault</ h2 >< div id = "userIdentity" class = "hint" ></ div ></ div >
< div class = "shellActions" >< button class = "primary" id = "addCredential" hidden > + Add credential</ button >< button id = "signOutButton" hidden > Sign out</ button >< a id = "signInLink" class = "buttonLink" href = "/signin" hidden > Sign in</ a ></ div >
2026-10-04 02:44:52 +00:00
</ div >
< div class = "vaultGroup" >
2026-10-04 08:05:18 +00:00
< div id = "userState" class = "state" hidden ></ div >
2026-10-04 02:44:52 +00:00
< div id = "userList" class = "list" ></ div >
</ div >
2026-10-04 08:05:18 +00:00
< div class = "vaultGroup" id = "namedVaults" hidden >
< div class = "groupHead" >< div >< strong > 📦 Vaults</ strong >< div class = "hint" > Private spaces for scoped Persimmons.</ div ></ div >< button id = "newVault" class = "primary" > + New vault</ button ></ div >
< div class = "groupRule" aria-hidden = "true" ></ div >
< div id = "namedVaultList" class = "list" aria-live = "polite" ></ div >
2026-10-04 02:44:52 +00:00
</ div >
</ section >
2026-10-04 08:05:18 +00:00
< footer class = "persimmonsFooter" >< strong > Passwords, PATs & plenty of other useful P’ s.</ strong >< div class = "vaultFlow" aria-label = "Orange to water to robot" > 🍊 → 💧 → 🤖</ div ></ footer >
2026-10-04 02:44:52 +00:00
</ main >
2026-10-04 08:05:18 +00:00
< script type = "module" src = "/assets/app.js" ></ script >
2026-10-04 02:44:52 +00:00
</ body >
2026-10-04 08:05:18 +00:00
</ html >